Java IO流
《文件传输基础——Java IO流》学习笔记
1.编码问题
public class EncodeDemo { public static void main(String[] args) throws Exception { String s = "慕课ABC"; byte[] bytes1 = s.getBytes();//项目默认编码GBK for (byte b: bytes1) { // 把字节(转换成int)以16进制显示 &0xff:只留下后八位 System.out.print(Integer.toHexString(b & 0xff) + " "); } System.out.println(); byte[] bytes2 = s.getBytes("gbk"); //c4 bd bf ce 41 42 43 //gbk 中文占2个字节 英文占1个字节 for (byte b: bytes2) { System.out.print(Integer.toHexString(b & 0xff) + " "); } System.out.println(); byte[] bytes3 = s.getBytes("utf-8"); //e6 85 95 e8 af be 41 42 43 //utf-8 中文占3个字节 英文占1个字节 for (byte b: bytes3) { System.out.print(Integer.toHexString(b & 0xff) + " "); } System.out.println(); // Java是双字节编码utf-16be byte[] bytes4 = s.getBytes("utf-16be"); //61 55 8b fe 0 41 0 42 0 43 //utf-16be中文占2个字节 英文占2个字节 for (byte b: bytes4) { System.out.print(Integer.toHexString(b & 0xff) + " "); } System.out.println(); /** * 当字节序列采用某种编码时 将字节序列转换成字符串 也需要使用相同编码 */ String str1 = new String(bytes4); System.out.println(str1); // 乱码 String str2 = new String(bytes4, "utf-16be"); System.out.println(str2); // 正常 } }
文本文件 就是字节序列 可以是任意编码的字节序列
如果在中文机器上直接创建文本文件,那么该文件只认识ANSI编码,但是粘贴过来的文件可以是任意格式。
Eclipse中一个只能识别项目默认的编码。
2.File类
Java.io.File类用于表示文件/目录
File只用于表示文件信息(名称、大小等),不能用于文件内容的访问。
package com.wenr.io; import java.io.File; import java.io.IOException; public class FileDemo { public static void main(String[] args) { // 构造函数 File file = new File("E:\\javaio"); if (!file.exists()) file.mkdir(); // 是否是一个目录 System.out.println(file.isDirectory()); // 是否是一个文件 System.out.println(file.isFile()); //File file2 = new File("E:\\javaio\\mdzz.txt"); File file2 = new File("E:\\javaio", "mdzz.txt"); if (!file2.exists()) { try { file2.createNewFile(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } else { file2.delete(); } System.out.println(file); System.out.println(file.getAbsolutePath()); System.out.println(file.getName() + " " + file.getParent()); System.out.println(file2.getName() + " " + file2.getParent()); } }
import java.io.File; import java.io.IOException; public class FileUtils { // 列出指定目录下(包括子目录)所有文件 public static void listDirectory(File dir) throws IOException { if (!dir.exists()) { throw new IllegalArgumentException("目录:" + dir + "不存在."); } if (!dir.isDirectory()) { throw new IllegalArgumentException(dir+"不是目录."); } //String[] filenames = dir.list(); // 返回子目录名称的字符处数组 File[] files = dir.listFiles(); for (File file: files) { if (file.isDirectory()) { FileUtils.listDirectory(file); } else { System.out.println(file); } } } public static void main(String[] args) throws IOException { FileUtils.listDirectory(new File("E:\\java")); } }
3.RandomAccessFile
Java提供的对文件内容的访问类,读写文件。可以随机访问文件。
Java文件模型,在硬盘上是Byte存储,是数据的集合。
打开文件,有两种模式"rw"(读写),"r"(只读)
写方法,raf.write(int)-->只写一个字节(后八位)
读方法, int b=raf.read()-->读一个字节
读完文件一定要关闭。
package com.wenr.io; import java.io.File; import java.io.IOException; import java.io.RandomAccessFile; import java.util.Arrays; public class RafDemo { public static void main(String[] args) throws IOException { File demo = new File("demo"); if (!demo.exists()) { demo.mkdir(); } File file = new File(demo, "raf.dat"); if (!file.exists()) { file.createNewFile(); } RandomAccessFile raf = new RandomAccessFile(file, "rw"); System.out.println(raf.getFilePointer()); raf.write('A'); System.out.println(raf.getFilePointer()); raf.write('B'); System.out.println(raf.getFilePointer()); int i = 0x7fffffff; // 用write方法每次只能写一个字节,如果要把i写进去就得写4次 raf.write(i >>> 24);//高8位 raf.write(i >>> 16); raf.write(i >>> 8); raf.write(i); System.out.println(raf.getFilePointer()); //可以直接写一个int raf.writeInt(i); System.out.println(raf.getFilePointer()); String s = "中"; byte[] gbk = s.getBytes(); raf.write(gbk); System.out.println(raf.length()); // 读文件 必须把指针移到头部 raf.seek(0); // 一次性读取 把文件中的内容都读到字节数组中 byte[] buf = new byte[(int)raf.length()]; raf.read(buf); System.out.println(Arrays.toString(buf)); for (byte b: buf) { System.out.print(Integer.toHexString(b & 0xff) + " "); } raf.close(); } }
4.字节流(char流)InputStream/OutputStream
1)字节流
InputStream(抽象类)抽象了应用程序读取数据方式
OutputStream(抽象类)抽象了应用程序写数据方式
2)EOF= End 读到-1就读到结束
3)输入流基本方法
int b = in.read();//读取一个字节填充到int第八位 -1是EOF
in.read(byte[] buf)
in.read(byte p[] buf, int start, int size);
4)输出流基本方式
out.write(int b) 写一个byte到流
out.write(byte[] buf) 将buf字节数组写入到流
out.write(byte[] buf, int start, int size);
5)FileInputStream--->具体实现了在文件上读取数据
(图片来源)
package com.wenr.io; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.OutputStream; import java.io.Serializable; public class TestIOStream { public static void testFileInputStream() throws IOException { // 文件输入流 InputStream in = new FileInputStream("demo/test.txt"); int x; // 读取文件demo/test.txt 读一个字节输出一个字节 while ((x = in.read()) != -1) { System.out.print(x + " "); } System.out.println(); in = new FileInputStream(new File("demo/test.txt")); byte[] b = new byte[20]; int off = 3; int len = 10; // 读取文件内容到数字b,从b[off]位置写入,最多读len长度的字节 // in.read(byte[] b) 相当于 read(b, 0, b.length) while ((x = in.read(b, off, len)) != -1) { for (byte bb: b) System.out.print(bb + " "); System.out.println(); } in.close(); } public static void testFileOutputStream() throws IOException { OutputStream out = new FileOutputStream("demo/test.txt"); int i = 0x01020304; // 只能写一字节到文件 蓝儿int有4字节 所以只输入了低8位 也就是04 out.write(i); byte[] b = {(byte)0xA,(byte)0xB, (byte)0xC, (byte)0xD, (byte)0xE, (byte)0xF}; // 把字节数组写入文件 out.write(b); // 向文件写入b[off] b[off+1] ... b[off+len-1] int off = 1, len = 2; out.write(b, off, len); out.close(); } static class People implements Serializable { String name; int age; People() {} People(String name, int age) { this.name = name; this.age = age; } public String toString() { return "name:" + name + ",age:" + age; } } public static void testObjectStream() throws FileNotFoundException, IOException, ClassNotFoundException { // 文件输出流 构造函数的参数是OutputStream 把对象序列化写入文件 ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("demo/test.txt")); People p1 = new People("张三", 21); People p2 = new People("李四", 22); oos.writeObject(p1); oos.writeObject(p2); oos.close(); // 对象输入流 构造函数的参数是InputStream ObjectInputStream ois = new ObjectInputStream(new FileInputStream("demo/test.txt")); People p = (People)ois.readObject(); System.out.println(p); p = (People)ois.readObject(); System.out.println(p); ois.close(); } public static void testBufferedStream() throws IOException { // 通过设置缓存区提高存取效率 BufferedInputStream bis = new BufferedInputStream(new FileInputStream("demo/test.txt")); BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("demo/test1.txt")); int i; while ((i = bis.read()) != -1) { bos.write(i); } bos.flush(); bis.close(); bos.close(); } public static void testDataStream() throws IOException { // 设置模式——>装饰模式 // 按格式读取 String file = "demo/dos.dat"; DataOutputStream dos = new DataOutputStream(new FileOutputStream(file)); dos.writeInt(10); dos.writeLong(-10L); dos.writeDouble(10.5); // 采用utf-8编码 dos.writeUTF("张三"); dos.close(); DataInputStream dis = new DataInputStream(new FileInputStream(file)); int i = dis.readInt(); long l = dis.readLong(); double d = dis.readDouble(); System.out.println(i + "," + l + "," + d); String s = dis.readUTF(); System.out.println(s); dis.close(); } public static void main(String[] args) throws IOException, ClassNotFoundException { //testFileOutputStream(); //testFileInputStream(); //testObjectStream(); //testBufferedStream(); testDataStream(); } }
5.字符流
字符流处理的一般是文本文件
1、字符流的基本实现
InputStreamReader 完成byte流解析为char流,按照编码解析
OutputStreamWriter 提供char流到byte流。
2、
FileWriter/FileWriter : 和InputStreamReader/OutputStreamWriter功能差不多,但是字符编码等设置是默认的。
3、字符流的过滤器
BufferedReader/BufferedWriter
package com.wenr.io; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.io.PrintWriter; public class TestCharSteam { public static void testInputStreamReader() throws IOException { InputStream in = new FileInputStream("demo/test.txt"); InputStreamReader isr = new InputStreamReader(in, "utf-8");// 默认项目编码 FileOutputStream out = new FileOutputStream("demo/test1.txt"); OutputStreamWriter osw = new OutputStreamWriter(out); int c; // 每次读取一个字符 // c = isr.read() char[] buffer = new char[20]; int count = 0; int a = 0; // 每次读取buffer.length个字符 while ((c = isr.read(buffer)) != -1) { String s = new String(buffer, 0, c); System.out.print(s); osw.write(buffer, 0, c); } osw.close(); } public static void testBuffered() throws IOException { // 构造参数 Reader BufferedReader br = new BufferedReader( new InputStreamReader( new FileInputStream("demo/test.txt"), "utf-8")); // BufferedWriter bw = new BufferedWriter( // new OutputStreamWriter( // new FileOutputStream("demo/test1.txt"))); PrintWriter pw = new PrintWriter("demo/test1.txt"); String line; while ((line = br.readLine()) != null) { // 读取一行不会读取换行! System.out.println(line); pw.println(line); pw.flush(); // bw.write(line); // bw.newLine(); } br.close(); //bw.close(); pw.close(); } public static void testFileWriterAndReader() throws IOException { // 不能设置编码 所以比编码不同的时候还是需要InputStreamReader&OutputStreamWriter FileReader fr = new FileReader("demo/test.txt"); FileWriter fw = new FileWriter("demo/test1.txt"); // FileWriter(fileName, true); true 表追加append char[] buffer = new char[2056]; int c; while ((c = fr.read(buffer)) != -1) { fw.write(buffer); } fr.close(); fw.close(); } public static void main(String[] args) throws IOException { // testInputStreamReader(); // testFileWriterAndReader(); testBuffered(); } }