黑马程序员-【IO流2】

时间:2023-02-18 09:43:18

                                                  -------android培训java培训、期待与您交流! ----------

字节流转化成字符流

OutputStreamWriter:把字节输出流对象转成字符输出流对象


InputStreamReader:把字节输入流对象转成字符输入流对象


FileWriter和FileReader分别是OutputStreamWriter和InputStreamReader的直接子类,而不是Writer和Reader的直接子类

 

例子:

 

//构建字节输出流对象
OutputStream out = new FileOutputStream("");
//把字节输出流转成字符输出流
Writer w = new OutputStreamWriter(out);


//构建一个字节输入流对象
InputStream is = new FileInputStream("");
//把字节输入流转成字符输入流
Reader r = new InputStreamReader(is);


 

内存操作流

 

之前的文件操作流是以文件的输入输出为主的,当输出的位置变成了内存,那么就称为内存操作流。此时要使用内存流完成内存的输入和输出操作。


如果程序运行过程中要产生一些临时文件,可采用虚拟文件方式实现;

ByteArrayInputStream的构造方法:


public ByteArrayInputStream(byte[] buf):全部内容


public ByteArrayInputStream(byte[] buf,int offset,int length):指定范围的内容


ByteArrayOutputStream的构造方法:


public ByteArrayOutputStream()


例子:

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;

public class ByteArrayDemo7 {
public static void main(String[] args) throws IOException {
String s = "hello heima";
ByteArrayOutputStream bos = new ByteArrayOutputStream();//输出流
bos.write(s.getBytes());
// 已经把信息写到了内存中

byte[] bys = bos.toByteArray();// 得到数据
ByteArrayInputStream bis = new ByteArrayInputStream(bys);//输入流,需要源。
byte[] b = new byte[1024];
int len;
while ((len = bis.read(b)) != -1) {
String data = new String(b, 0, len);
System.out.println(data);
}
}
}


package june6D;

import java.io.CharArrayReader;
import java.io.CharArrayWriter;

public class CharArrayDemo8 {

public static void main(String[] args) throws Exception {
// 用内存字符流先把数据保存到内存中,然后从内存中取出数据
String s = "hello workd";
CharArrayWriter cw = new CharArrayWriter();
cw.write(s);// 数据写到了内存中
char[] ch = cw.toCharArray();
CharArrayReader cr = new CharArrayReader(ch);
char[] b = new char[1024];
int len;
while ((len = cr.read(b)) != -1) {
String data = new String(b, 0, len);
System.out.println(data);
}
}
}


 

对象序列化

 

操作的对象为:ObjectInputStream与ObjectOutputStream

 

import java.io.*;

class ObjectStreamDemo {
public static void main(String[] args) {

}

public static void writeObj() {
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("obj.txt"));
}
}

 

RandomAccessFIle类


RandomAccessFile的唯一父类是Object,与其他流父类不同。是用来访问那些保存数据记录的文件的,这样你就可以用seek( )方法来访问记录,并进行读写了。这些记录的大

小不必相同;但是其大小和位置必须是可知的。


RandomAccessFile是不属于InputStream和OutputStream类系的。实际上,除了实现DataInput和DataOutput接口之外(DataInputStream和DataOutputStream也实现了这两个接

口),它和这两个类系毫不相干,甚至都没有用InputStream和OutputStream已经准备好的功能;它是一个完全独立的类,所有方法(绝大多数都只属于它自己)都是从零开始写

的。这可能是因为RandomAccessFile能在文件里面前后移动,所以它的行为与其它的I/O类有些根本性的不同。总而言之,它是一个直接继承Object的,独立的类。

 

例子:

 

import java.io.*;

class RandomAccessFileDemo {
public static void main(String[] args)throws IOException
{
//writeFile();
//readFile();
writeFile_2()
}

public static void readFile() throws IOException {
RandomAccessFile raf = new RandomAccessFile("ran.txt", "r");

// 调整对象指针
raf.seek(8);

// 跳过指定的字节数
raf.skipBytes(8);// 只能往前跳 不能往后跳

byte[] buf = new byte[4];

raf.read(buf);

String name = new String(buf);

int age = raf.readInt();

System.out.println("name=" + name);
System.out.println("age=" + age);

raf.close();
}

public static void writeFile_2() throws IOException {
RandomAccessFile raf = new RandomAccessFile("ran.txt", "rw");
raf.seek(8 * 3);
// raf.seek(8*0);//会对数据进行覆写
raf.write("周期".getBytes());
raf.writeInt(103);

raf.close();
}

public static void writeFile() throws IOException {
RandomAccessFile raf = new RandomAccessFile("ran.txt", "rw");
raf.write("李四".getBytes());
// raf.write(258);//write只写出最低八位,超出八位的话会数据丢失
raf.writeInt(97);// writeInt(int v) 按四个字节将 int 写入该文件,先写高字节
raf.write("王五".getBytes());
raf.writeInt(99);

raf.close();

}
}


打印流:PrintWriter和PrintStream

 

打印流有非常好的打印功能,可以打印任何的数据类型。如,整数,小数,字符串等

 

PrintStream类的构造:


public PrintStream(File file) throws FileNotFoundException

public PrintStream(OutputStream out)

实例化的时候依然需要传入一个OutputStream的对象。

PrintWriter和PrintStream都属于输出流,分别针对字符和字节。

PrintWriter和PrintStream重载的print()和println()用于多种数据类型的输出。

print()里的参数不能为空;println()可以

PrintWriter和PrintStream输出操作不抛出异常

PrintStream调用println方法有自动flush功能;

例子:

 

import java.io.FileWriter;
import java.io.PrintStream;
import java.io.PrintWriter;

public class PrintDemo9 {
public static void main(String[] args) throws Exception {

PrintStream ps = new PrintStream("out.txt");
// ps.write(12);
ps.println(10086);
ps.println(false);
ps.println();// 此时就可以
ps = System.out;
ps.println("hello!");// 控制台操作,注意上一句
// 字符打印流
PrintWriter pr = new PrintWriter("out2.txt");
// PrintWriter(OutputStream out, boolean autoFlush) 通过现有的 OutputStream,创建新的 PrintWriter。(构造方法)

pr = new PrintWriter(new FileWriter("out2.txt"), true);// 自动刷新,否则的话需要关闭资源!
// 与PrintStream不同,若PrintWriter使用了自动刷新方法,那么必须调用println,print,format这些方法的其中一个才可以实现操作
pr.println("hello world");
pr.println(false);

pr = new PrintWriter(System.out, true);// 打印在控制台上
pr.println(false);
pr.println("nihaoya");
pr.println(374822);
// pr.close();//因为使用了自动刷新。
}
}


缓冲流

 

缓冲流要“套接”在相应的节点流之上,对读写的数据提供了缓冲的功能,提高了读写效率,同时增加了一些新的方法。


四种缓冲流

BufferedReader(Reader in)

BufferedReader(Reader in,int sz)//sz表示自定义缓冲区大小

BufferedWriter(Writer out)

BufferedWriter(Writer out,int sz)

BufferedInputStream(InputStream in)

BufferedInputStream(InputStream in,int sz)

BufferedOutputStream(OutputStream out)

BufferedOutputStream(OutputStream out,int sz)

 

BufferedReader提供readLine方法用于读取一行字符串。

BufferedWriter提供了newLine方法用于写入一个行分隔符。等价于//.writer("\r\n");

对于输出的缓冲流,写出的数据会先在内存中缓冲,使用flush方法将会使内存中的数据立刻写出。

例子:

 

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

//用缓冲流,性能相对高些
public class BufferedInputStreamDemo22 {
public static void main(String[] args) throws IOException {
/*
* BufferedInputStream bis = new BufferedInputStream(new
* FileInputStream("68.txt")); BufferedOutputStream bos = new
* BufferedOutputStream(new FileOutputStream("buffer.txt"));
*
* int len = 0;
* while((len = bis.read()) != -1){
* bos.write(len);
* }
* bos.close();
* bis.close();
*/

try (
BufferedReader br = new BufferedReader(new FileReader("68.txt"));
BufferedWriter bw = new BufferedWriter(new FileWriter(
"bufferWriter.txt")))
{//java7新特性,自动关闭资源
String Line = null;
while ((Line = br.readLine()) != null) {
bw.write(Line);
bw.newLine();//此时必须加上换行操作,注意这是个新用法(方法)
}
} catch (Exception e) {
e.printStackTrace();
}
}
}



合并流:SequenceInputStream

 

将两个文件的内容合并成一个文件


该类提供的方法:


SequenceInputStream(InputStream s1, InputStream s2) :根据两个字节输入流对象来创建合并流对象。

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.SequenceInputStream;

//和并两个文件的合并流
public class SequenceInputStreamDemo24 {
public static void main(String[] args) throws IOException {

SequenceInputStream si = new SequenceInputStream(
new FileInputStream("hello"),
new FileInputStream("world!"));

OutputStream ost = new FileOutputStream("sequence.txt");
int len;
byte []b = new byte[1024];
while((len = si.read(b)) != -1){
ost.write(b, 0, len);
}
}
}


切割文件

import java.io.*;
import java.util.*;

class SplitFile {
public static void main(String[] args) {
// splitFile();
merge();
}

public static void merge()
{
ArrayList<FileInputStream> al = new ArrayList<FileInputStream>();

for(int x=1;x<=5;x++)
{
al.add(new FileInputStream("e:\\Java练习\\"+(x++)+".part"))
}

Iterator it = al.iterator();

Enumeration<FileInputStream> en = new Enumeration<FileInputStream>()
{
public boolean hasMoreElements()
{
return it.hasNext();
}
public FileInputStream nextElement()
{
return it.next();
}
};

SequenceInputStream sis = new SequenceInputStream(en);

FileOutputStream fos = new FileOutputStream("e:\\Java练习\\1.mp3");

byte[] buf = new byte[1024];

int len = 0;

while((len=sis.read())!=-1)
{
fos.write(buf,0,len)
}
fos.close();
sis.close();
}

public static void splitFile()
{
FileInputStream fis = new FileInputStream("e:\\Java练习\\0.mp3");

FileOutputStream fos = null;

byte[] buf = new byte[1024*1024];

int len = 0;
int x = 1;
while((len=fis.read(buf))!=-1)
{
fos = new FileOutputStream("e:\\Java练习\\"+(x++)+".part")
fos.write(buf,0,len);
fos.close();
}
fis.close();
}
}

 

“联通问题”

 

class EncodeDemo2 {
public static void main(String[] args) {
String s = "联通";

byte[] by = s.getBytes("gbk");

for (byte b : by) {
System.out.println(Integer.toBinaryString(b & 255));
}
}
}


编码

 

 字符流的出现为了方便操作字符,本质上就是对字节流进行了编解码的操作

  主要通过下面子类转换流来完成:InputStreamReader 和OutputStreamWriter

  在两个对象进行构造的时候可以加入字符集

 
  计算机只能识别二进制数据,为了方便应用计算机,让它可以识别各个国家的文字,就将各个国家的文字用数字来表示,并一一对应,形成一张表,这就是编码表

  常见的编码表

  ASCII:美国标准信息交换码。 用一个字节的7位可以表示

  ISO08859-1:拉丁码表。欧洲码表

  GBK/GB2312:中文国际编码,专门用来表示汉字

  Unicode:java中使用此编码方式,是最标准的一种编码

 UTF-8:最多用三个字节来表示一个字符


   例子:

import java.io.*;

class EncodeStream {
public static void main(String[] args) throws IOException {
writeText();
}

public static void readText() throws IOException {
InputStreamReader isr = new InputStreamReade(new FileInputStream("gbk.txt"), "gbk");

char[] buf = new char[10];
int len = isr.read(buf);

String str = new String(buf, 0, len);

System.out.println(str);
isr.close();
}

public static void writeText() throws IOException {
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("gbk.txt"), "gbk");
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("utf.txt"), "UTF-8");
osw.write("你好");

osw.close();

}

}