文件 - File类
- File对象
1、用来将文件或者文件夹封装成对象 2、方便对文件与文件夹的属性信息进行操作 3、File对象可以作为参数传递给流的构造函数
public class Test { public static void main(String[] args) { File f = new File("e:\\"); System.out.println(new File("e:\\demo.txt")); System.out.println(new File("e:\\", "demo.txt")); System.out.println(new File(f, "demo.txt")); System.out.println(new File("e:" + File.separator + "demo.txt")); } } /** 输出 e:\demo.txt e:\demo.txt e:\demo.txt e:\demo.txt */
- File对象 - 常见功能
1.获取
1.1 获取文件名称 - getName() 1.2 获取文件路径 - getPath()/getAbsolutePath() 1.3 获取文件大小 - length() 1.4 获取文件修改时间 - lastModified()
2.创建与删除
2.1 创建文件 - createNewFile():和输出流不一样,如果文件不存在,则创建,如果文件存在,则不创建 - mkdir():创建目录 2.2 删除文件 - delete():当使用delete()删除目录时,如果不是空文件夹会删除失败 - deleteOnExit():在虚拟机终止时,请求删除此抽象路径名表示的文件或目录
3.判断
3.1 判断是否存在 - exists() 3.2 判断是否是目录 - isDirectory() 3.3 判断是否是文件 - isFile()
4.重命名
4.1 重命名 - renameTo(File dest)
5.列出目录和容器获取
5.1 获取可用的文件系统根 - listRoots() 5.2 获取抽象路径名指定的分区大小 - getTotalSpace() 5.3 获取抽象路径名指定的分区中未分配的字节数 - getFreeSpace() 5.4 获取抽象路径名指定的分区上可用于此虚拟机的字节数 - getUsableSpace() 5.5 获取目录中的文件和目录,包含隐藏文件 - String[] list() =>只能通过目录去调用,否则空指针异常,如果目录存在但没有内容,则返回长度为0的数组 5.6 获取目录中按照特定过滤器过滤后的文件和目录 - String[] list(FilenameFilter filter)
- 实例
public class Test { public static void main(String[] args) throws IOException { File file = new File("demo.txt"); File absFile = new File("C:\\Users\\Administrator\\workspace\\HelloJava\\demo.txt"); String name = file.getName(); String absPath = file.getAbsolutePath(); String path = file.getPath(); long length = file.length(); long time = file.lastModified(); String lastModifiedTime = getTime(time); String parentPath = file.getParent(); String absFileParentPath = absFile.getParent(); System.out.println("parentPath:" + parentPath + " ==> absFileParentPath:" + absFileParentPath); // 删除创建文件 file.delete(); file.createNewFile(); System.out.println("lastModifiedTime:" + lastModifiedTime + " ==> new:" + getTime(file.lastModified())); File dir = new File("test\\a\\b\\c"); // 创建目录 dir.mkdir(); dir.delete(); // 如果c不是空文件夹,将删除失败;并且只能删除c文件夹 // 文件或目录是否存在 boolean isExist = file.exists(); boolean isAbsolute = file.isAbsolute(); boolean isFile = file.isFile(); boolean isDir = dir.isDirectory(); File dest = new File("text.txt"); // 重命名 file.renameTo(dest); // 剪切 dest.renameTo(new File("e:\\abc.txt")); File[] files = File.listRoots(); for (File f : files) { long free = f.getFreeSpace(); long total = f.getTotalSpace(); // 返回此抽象路径名指定的分区上可用于此虚拟机的字节数 long usable = f.getUsableSpace(); } // list方法只能使用目录去调用,文件调用会返回null String[] list = absFile.list(); System.out.println(file.list()); File workspace = new File("C:\\Users\\Administrator\\workspace\\HelloJava"); list = workspace.list(new SuffixFilter(".txt")); for (String string : list) { System.out.println(string); } files = workspace.listFiles(new FilterByHidden()); for (File f : files) { System.out.println(f); } } private static String getTime(long time) { Date date = new Date(time); DateFormat format = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT); return format.format(date); } } class SuffixFilter implements FilenameFilter { private String suffix = null; public SuffixFilter(String suffix) { super(); this.suffix = suffix; } public boolean accept(File dir, String name) { return name.endsWith(suffix); } } class FilterByHidden implements FileFilter { public boolean accept(File pathname) { return pathname.isHidden(); } } /** * 输出 : parentPath:null ==> absFileParentPath:C:\Users\Administrator\workspace\HelloJava lastModifiedTime:16-2-17 下午10:11 ==> new:16-2-17 下午10:18 null demo.txt fileWriter.txt text.txt */
// 深度遍历目录 public class Test { public static void main(String[] args) throws IOException { File dir = new File("C:\\Users\\Administrator\\workspace\\HelloJava\\bin"); listAll(dir, 0); deleteAll(dir); } // 深度遍历目录 private static void listAll(File dir, int level) { File[] files = dir.listFiles(); level++; for (int i = 0; i < files.length; i++) { if (files[i].isDirectory()) { // 递归调用,一个功能在被重复使用,并每次使用时参与运算的结果和上一次调用有关 // 注意: // 1.递归一定明确条件,否则容易栈溢出 // 2.注意一下递归次数 listAll(files[i], level); } else { System.out.println(level + ":" + files[i].getAbsolutePath()); } } } // 删除目录,需要从里往外删除 private static void deleteAll(File dir) { File[] files = dir.listFiles(); for (int i = 0; i < files.length; i++) { if (files[i].isDirectory()) { deleteAll(files[i]); } else { files[i].delete(); } } dir.delete(); } }
// 文件切割、合并 public class Test { private static final int SIZE = 1024; public static void main(String[] args) throws IOException { File file = new File("e:\\tone.mp3"); spitFile(file); mergeFile(new File("e:\\test")); } // 文件切割 private static void spitFile(File file) throws IOException { FileInputStream fis = new FileInputStream(file); Properties prop = new Properties(); byte[] buff = new byte[SIZE * 100]; FileOutputStream fos = null; int len = 0; int count = 1; File dir = new File("e:\\test"); if (!dir.exists()) { dir.mkdir(); } while ((len = fis.read(buff)) != -1) { fos = new FileOutputStream(new File(dir, (count++) + ".part")); fos.write(buff, 0, len); fos.close(); } // 将文件切割信息保存到属性中 prop.setProperty("count", count + ""); prop.setProperty("name", file.getName()); // 将属性保存到.prop 配置信息中 fos = new FileOutputStream(new File(dir, (count++) + ".prop")); prop.store(fos, "save file prop"); fos.close(); fis.close(); } // 文件合并 private static void mergeFile(File dir) throws IOException { File[] files = dir.listFiles(new SuffixFilter(".prop")); if (files.length != 1) { throw new RuntimeException("Filename not match.."); } File config = files[0]; // 获取配置文件信息 Properties prop = new Properties(); FileInputStream fis = new FileInputStream(config); prop.load(fis); String name = prop.getProperty("name"); int count = Integer.parseInt(prop.getProperty("count")); File[] parts = dir.listFiles(new SuffixFilter(".part")); if (parts.length != count - 1) { throw new RuntimeException("Part length not match.."); } ArrayList<FileInputStream> al = new ArrayList<FileInputStream>(); for (int i = 1; i < count; i++) { al.add(new FileInputStream(new File(dir, i + ".part"))); } Enumeration<FileInputStream> en = Collections.enumeration(al); SequenceInputStream sis = new SequenceInputStream(en); FileOutputStream fos = new FileOutputStream(new File(dir, name)); byte[] buff = new byte[SIZE * 100]; int len = 0; while ((len = sis.read(buff)) != -1) { fos.write(buff, 0, len); } fos.close(); sis.close(); } } class SuffixFilter implements FilenameFilter { private String suffix = null; public SuffixFilter(String suffix) { super(); this.suffix = suffix; } public boolean accept(File dir, String name) { return name.endsWith(suffix); } }
流分类
- 按流向分为:输入流与输出流
输入流和输出流相对于内存设备而言
输入:将外设中的数据读取到内存中 输出:将内存中国的数据写入到外设中
- 按照操作数据分为:字节流与字符流
字符流的由来:字节流读取文字字节数据后,不直接操作而是先查指定的编码表,获取对应的文字,再对这个文字进行操作 简单说:字符流 = 字符流+编码表
IO体系的子类都以父类名作为后缀,而且子类名的前缀就是该对象的功能
字符流 - Reader/Writer
如果要操作文字数据,建议优先考虑字符流,而且要将数据从内存写到硬盘上,要使用字符流中的输出流-Writer,硬盘的数据基本体现是文件
- 字符流 - 写入文件(FileWriter)
public class Test { // 换行 private static final String LINE_SEPARATOR = System.lineSeparator(); public static void main(String[] args) throws IOException { File file = new File("e:\\fileWriter.txt"); fileWrite(file, "FileWriter"); } private static void fileWrite(File path, String input) throws IOException { // 如果文件不存在,则创建;如果文件存在,则覆盖 FileWriter writer = new FileWriter(path); //FileWriter writer = new FileWriter(path, true); //续写构造函数 // FileWriter(File file, boolean append):续写 // 写入数据 writer.write(input + LINE_SEPARATOR); // 进行刷新,将数据直接写到目的地中 writer.flush(); writer.append(input + LINE_SEPARATOR); // 在关闭前会调用flush()刷新缓冲池中的数据到目的地 writer.close(); } }
- 字符流 - 读取文件(FileReader)
public class Test { public static void main(String[] args) { File file = new File("e:\\demo.txt"); System.out.println(readFile(file)); } private static String readFile(File path) { FileReader reader = null; StringBuilder builder = new StringBuilder(); try { reader = new FileReader(path); int ch = 0; while ((ch = reader.read()) != -1) { builder.append((char) ch); } } catch (IOException e) { e.printStackTrace(); } finally { try { if (reader != null) reader.close(); } catch (IOException e) { throw new RuntimeException("Close fail!"); } } return builder.toString(); } }
- 字符流 - 文件读写操作(复制)
public class Test { public static void main(String[] args) { File in = new File("e:\\demo.txt"); File out = new File("e:\\copy.txt"); copyFile(in, out); } private static void copyFile(File in, File out) { FileReader reader = null; FileWriter writer = null; try { /* 效率较低 reader = new FileReader(in); writer = new FileWriter(out); int ch = 0; while ((ch = reader.read()) != -1) { writer.write(ch); } */ reader = new FileReader(in); writer = new FileWriter(out); char[] ch = new char[1024]; int len = 0; while ((len = reader.read(ch)) != -1) { writer.write(ch, 0, len); } } catch (IOException e) { e.printStackTrace(); } finally { try { if (reader != null) { reader.close(); } if (writer != null) { writer.close(); } } catch (IOException e) { throw new RuntimeException("Close fail!"); } } } }
- 字符流 - 缓冲区(BufferedWriter/BufferedReader)
特点: 1. 缓冲区的出现提供了对数据的读写效率 2. 缓冲区要结合流才可以使用 3. 在流的基础上对流的功能进行了增强
BufferedReader:从字符输入流中读取文本,缓冲各个字符,从而实现字符、数组和行的高效读取。 public String readLine():读取一个文本行。通过下列字符之一即可认为某行已终止:换行 ('\n')、回车 ('\r') 或回车后直接跟着换行。 BufferedWriter:将文本写入字符输出流,缓冲各个字符,从而提供单个字符、数组和字符串的高效写入。 public void newLine():写入一个行分隔符。行分隔符字符串由系统属性 line.separator 定义,并且不一定是单个新行 ('\n') 符。
BufferedReader 使用了装饰模式 装饰设计模式:对一组对象的功能进行增强时,就可以使用该模式进行问题的解决 装饰比继承灵活 特点:装饰类和被装饰类都必须所属同一个接口或者父类
public class Test { public static void main(String[] args) { File in = new File("e:\\demo.txt"); File out = new File("e:\\copy.txt"); copyFile(in, out); } private static void copyFile(File in, File out) { FileReader reader = null; BufferedReader bufReader = null; FileWriter writer = null; BufferedWriter bufWriter = null; try { reader = new FileReader(in); bufReader = new BufferedReader(reader); writer = new FileWriter(out); bufWriter = new BufferedWriter(writer); String line = null; while ((line = bufReader.readLine()) != null) { bufWriter.write(line); bufWriter.newLine(); bufWriter.flush(); } } catch (IOException e) { e.printStackTrace(); } finally { try { if (bufReader != null) { bufReader.close(); } if (bufWriter != null) { bufWriter.close(); } } catch (IOException e) { throw new RuntimeException("Close fail!"); } } } }
// 自定义BufferedReader public class Test { public static void main(String[] args) { File file = new File("e:\\demo.txt"); readFile(file); } private static void readFile(File file) { FileReader reader = null; CustomBufferedReader bufReader = null; try { reader = new FileReader(file); bufReader = new CustomBufferedReader(reader); String line = null; while ((line = bufReader.readLine()) != null) { System.out.println(line); } } catch (IOException e) { e.printStackTrace(); } finally { try { if (bufReader != null) { bufReader.close(); } } catch (IOException e) { throw new RuntimeException("Close fail!"); } } } } class CustomBufferedReader { char[] buffer = new char[1024]; Reader reader = null; private int count = 0; private int pos = 0; CustomBufferedReader(Reader reader) { this.reader = reader; } public int read() throws IOException { if (count == 0) { count = reader.read(buffer); pos = 0; } if (count < 0) { return -1; } char ch = buffer[pos++]; count--; return ch; } public String readLine() throws IOException { StringBuilder sb = new StringBuilder(); int ch = 0; while ((ch = read()) != -1) { if (ch == '\r') continue; if (ch == '\n') return sb.toString(); sb.append((char) ch); } if (sb.length() > 0) return sb.toString(); return null; } public void close() throws IOException { reader.close(); } }
- 字符流 - 缓冲区(BufferedReader子类:LineNumberReader)
public class Test { public static void main(String[] args) { File file = new File("e:\\demo.txt"); readFile(file); } private static void readFile(File file) { FileReader reader = null; LineNumberReader bufReader = null; try { reader = new FileReader(file); bufReader = new LineNumberReader(reader); String line = null; bufReader.setLineNumber(2); while ((line = bufReader.readLine()) != null) { System.out.println(bufReader.getLineNumber() + ":" + line); } } catch (IOException e) { e.printStackTrace(); } finally { try { if (bufReader != null) { bufReader.close(); } } catch (IOException e) { throw new RuntimeException("Close fail!"); } } } }
- 转换流 - InputStreamReader/OutputStreamWriter
转换流 - 字节转字符 InputStreamReader:是字节流通向字符流的桥梁:它使用指定的 charset 读取字节并将其解码为字符。
转换流 - 字符转字节 OutputStreamWriter:是字符流通向字节流的桥梁:可使用指定的 charset 将要写入流中的字符编码成字节。 它使用的字符集可以由名称指定或显式给定,否则将接受平台默认的字符集。
public class Test { public static void main(String[] args) { try { readFromKeyboard(); } catch (IOException e) { e.printStackTrace(); } } private static void readFromKeyboard() throws IOException { /* InputStream is = System.in; // 字节流转字符流 InputStreamReader isr = new InputStreamReader(is); BufferedReader reader = new BufferedReader(isr); OutputStream os = System.out; // 字符流转字节流 OutputStreamWriter osw = new OutputStreamWriter(os); BufferedWriter writer = new BufferedWriter(osw); */ BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(System.out)); String line = null; while ((line = reader.readLine()) != null) { if (line.equals("over")) { break; } writer.write(line.toUpperCase()); writer.newLine(); writer.flush(); } } }
字节流 - InputStream/OutputStream
- 字节流操作文件不需要缓冲,直接写入到了目的文件中
public class Test { public static void main(String[] args) { File file = new File("e:\\demo.txt"); try { writeFile(file, "Android" + System.lineSeparator() + "Java"); readFile(file); } catch (IOException e) { e.printStackTrace(); } } private static void readFile(File file) throws IOException { FileInputStream fis = new FileInputStream(file); byte[] buf = new byte[1024]; int len = 0; while ((len = fis.read(buf)) != -1) { System.out.println(new String(buf, 0, len)); } /* 尽量少用available(),文件过大容易造成内存溢出 byte[] buf = new byte[fis.available()]; fis.read(buf); System.out.println(new String(buf)); */ fis.close(); } private static void writeFile(File file, String in) throws IOException { FileOutputStream fos = new FileOutputStream(file); fos.write(in.getBytes()); fos.close(); } }
- 使用字节流拷贝图片
public class Test { public static void main(String[] args) { try { copyPic_1(); copyPic_2(); copyPic_3(); copyPic_4(); } catch (IOException e) { e.printStackTrace(); } } private static void copyPic_1() throws IOException { FileInputStream fis = new FileInputStream(new File("e:\\pic.jpg")); FileOutputStream fos = new FileOutputStream(new File("e:\\pic_1.jpg")); byte[] buf = new byte[1024]; int len = 0; while ((len = fis.read(buf)) != -1) { fos.write(buf, 0, len); } fos.close(); fis.close(); } // 不建议使用,available()会影响性能 private static void copyPic_2() throws IOException { FileInputStream fis = new FileInputStream(new File("e:\\pic.jpg")); FileOutputStream fos = new FileOutputStream(new File("e:\\pic_2.jpg")); byte[] buf = new byte[fis.available()]; fis.read(buf); fos.write(buf); fos.close(); fis.close(); } // 不会使用,毫无效率,慢得不行! private static void copyPic_3() throws IOException { FileInputStream fis = new FileInputStream(new File("e:\\pic.jpg")); FileOutputStream fos = new FileOutputStream(new File("e:\\pic_3.jpg")); int ch = 0; while ((ch = fis.read()) != -1) { fos.write(ch); } fos.close(); fis.close(); } private static void copyPic_4() throws IOException { FileInputStream fis = new FileInputStream(new File("e:\\pic.jpg")); BufferedInputStream bufis = new BufferedInputStream(fis); FileOutputStream fos = new FileOutputStream(new File("e:\\pic_4.jpg")); BufferedOutputStream bufos = new BufferedOutputStream(fos); int ch = 0; while ((ch = bufis.read()) != -1) { bufos.write(ch); } bufis.close(); bufos.close(); } }
- 键盘录入 - System.in
public class Test { public static void main(String[] args) { try { readFromKeyboard(); } catch (IOException e) { e.printStackTrace(); } } private static void readFromKeyboard() throws IOException { InputStream is = System.in; StringBuilder sb = new StringBuilder(); int ch = 0; // read()是阻塞方法 while ((ch = is.read()) != -1) { if (ch == '\r') { continue; } if (ch == '\n') { String tmp = sb.toString(); if (tmp.equals("over")) { break; } System.out.println(tmp.toUpperCase()); sb.delete(0, sb.length()); } else { sb.append((char) ch); } } //从System.in获取的流对象只有一个,不需要关闭流,该流会随系统自动关闭 //关闭了就很难获取到 //is.close(); } }
- 对象的序列化与反序列化 - ObjectInputStream/ObjectOutputStream
通过在流中使用文件可以实现对象的持久存储
ObjectOutputStream:将 Java 对象的基本数据类型和图形写入 OutputStream,即将对象写入文件中 ObjectInputStream:对以前使用 ObjectOutputStream 写入的基本数据和对象进行反序列化,即从文件中读取对象
public class Test { public static void main(String[] args) throws IOException, ClassNotFoundException { File file = new File("e:\\person.object"); writeObj(new Person("zhangsan", 23, 1000, "xiaozhang"), file); readObj(file); } // 保存对象到硬盘上,保存的对象需要序列化 private static void writeObj(Person person, File file) throws IOException { ObjectOutputStream oop = new ObjectOutputStream(new FileOutputStream(file)); // 对象序列话。被序列话的对象必须实现Serializable接口 oop.writeObject(person); oop.close(); } private static void readObj(File file) throws IOException, ClassNotFoundException { ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file)); // 对象的反序列化 Person person = (Person) ois.readObject(); System.out.println(person.name + " : " + person.age + " : " + person.money + " : " + person.nike); ois.close(); } } /** * Serializable:用于给被序列号的类加入ID号,用于判断类和对象是否是同一版本 */ class Person implements Serializable /** 标记接口 */ { // 通过该ID 判断对象和类是否是同一版本 private static final long serialVersionUID = 2L; public String name; public int age; // static 不能被序列化保存到硬盘上,因为static不属于对象 public static int money; // transient:非static的,不被序列化可以使用该关键字 public transient String nike; public Person(String name, int age, int money, String nike) { this.name = name; this.age = age; this.money = money; this.nike = nike; } }
- 管道流 - PipedInputStream/PipedOutputStream
输入输出可以直接进行连接,通过结合线程使用
不建议对这两个对象尝试使用单个线程,因为这样可能会造成该线程死锁
public class Test { public static void main(String[] args) throws IOException { PipedInputStream input = new PipedInputStream(); PipedOutputStream output = new PipedOutputStream(); input.connect(output); // 关联起来 // PipedOutputStream output = new PipedOutputStream(input); //关联起来 new Thread(new Input(input)).start(); new Thread(new Out(output)).start(); } } class Input implements Runnable { private PipedInputStream in; public Input(PipedInputStream in) { this.in = in; } public void run() { try { byte[] buf = new byte[1024]; int len = in.read(buf); String s = new String(buf, 0, len); System.out.println("s:" + s); in.close(); } catch (Exception e) { // TODO: handle exception } } } class Out implements Runnable { private PipedOutputStream out; public Out(PipedOutputStream out) { this.out = out; } public void run() { try { out.write("PipedOutputStream ...".getBytes()); out.close(); } catch (Exception e) { // TODO: handle exception } } } // 输出: // s:PipedOutputStream ...
- 操作基本数据类型 - DataInputStream/DataOutputStream
应用程序可以使用数据输出流写入稍后由数据输入流读取的数据
DataInputStream 对于多线程访问不一定是安全的
public class Test { public static void main(String[] args) throws IOException { File file = new File("e:\\data.txt"); writeData(file); readData(file); } private static void writeData(File file) throws IOException { DataOutputStream dos = new DataOutputStream(new FileOutputStream(file)); dos.writeUTF("Hello DataOutputStream"); dos.close(); } private static void readData(File file) throws IOException { DataInputStream dis = new DataInputStream(new FileInputStream(file)); String utf = dis.readUTF(); System.out.println(utf); } } // 输出: // Hello DataOutputStream
- 操作字节数组 - ByteArrayInputStream/ByteArrayOutputStream
ByteArrayInputStream 包含一个内部缓冲区,该缓冲区包含从流中读取的字节
关闭 ByteArrayInputStream 无效。此类中的方法在关闭此流后仍可被调用,而不会产生任何 IOException(因为该对象并没有操作底层资源)
public class Test { public static void main(String[] args) throws IOException { ByteArrayInputStream bis = new ByteArrayInputStream("ByteArrayInputStream".getBytes()); ByteArrayOutputStream bos = new ByteArrayOutputStream(); int ch = 0; while ((ch = bis.read()) != -1) { bos.write(ch); } System.out.println(bos.toString()); } } // 输出: // ByteArrayInputStream
随机访问文件 - RandomAccessFile
支持对随机访问文件的读取和写入 1.随机访问文件,自身具备读写的方法 2.通过skipBytes(int x),seek(int x)来达到随机访问
- 特点
1. 该对象既能读,又能写 2. 该对象内部维护了一个byte数组,并通过指针可以操作数组中的元素 3. 可以通过getFilePointer方法获取指针的位置,和通过seek方法设置指针的位置 4. 该对象就是字节输入流和输出流进行了封装 5. 该对象的源或者目的只能是文件。通过构造函数可以看出
public class Test { public static void main(String[] args) throws IOException { File file = new File("e:\\random.txt"); writeFile(file); randomWrite(file); randomRead(file); } private static void writeFile(File file) throws IOException { // 如果文件不存在,则创建;如果文件存在,则不创建 RandomAccessFile raf = new RandomAccessFile(file, "rw"); raf.write("zhangsan".getBytes()); raf.writeInt(22); raf.write("lisi".getBytes()); raf.writeInt(25); raf.close(); } private static void randomWrite(File file) throws IOException { // 如果文件不存在,则创建;如果文件存在,则不创建 RandomAccessFile raf = new RandomAccessFile(file, "rw"); raf.seek(12); // 随机写入,只要指定指针的位置即可 raf.write("wangwu".getBytes()); raf.writeInt(25); raf.close(); } // 可以用于多线程写入 private static void randomRead(File file) throws IOException { RandomAccessFile raf = new RandomAccessFile(file, "r"); // 通过seek设置指针位置 raf.seek(12); // 随机读取,只要指定指针的位置即可 byte[] buf = new byte[6]; raf.read(buf); System.out.println("name:" + new String(buf) + " age:" + raf.readInt()); raf.close(); } } // 输出: // name:wangwu age:25
异常处理 - IOException
public class Test { // 换行 private static final String LINE_SEPARATOR = System.lineSeparator(); public static void main(String[] args) { File file = new File("h:\\fileWriter.txt"); writeFile(file, "FileWriter"); } private static void writeFile(File path, String input) { FileWriter writer = null; try { writer = new FileWriter(path); writer.append(input + LINE_SEPARATOR); } catch (IOException e) { e.printStackTrace(); } finally { try { if (writer != null) writer.close(); } catch (IOException e) { throw new RuntimeException("Close fail!"); } } } } // java.io.FileNotFoundException
编码
- 常见编码表
ASCII:美国标准信息交换吗 =>用一个字节的7位可以表示 ISO8859-1:拉丁码表。欧洲码表 =>用一个字节的8位表示 GB2312:中国的中文编码表 GBK:中国的中文编码表升级 Unicode:国际标准码,融合了多种文字。 =>所有文字都用两个字节来表示,java语言使用的就是unicode UTF-8:最多用三个字节来表示一个字符
字符串-->字节数组:编码 字节数组-->字符串:解码
public class Test { public static void main(String[] args) throws IOException { String str = "你好"; // 编码 byte[] buf_gbk = str.getBytes("GBK"); byte[] buf_utf = str.getBytes("utf-8"); // 解码 printBytes(buf_gbk); printBytes(buf_utf); } private static void printBytes(byte[] buf) { for (byte b : buf) { System.out.print(b + " "); } System.out.println(); } } // 输出: // -60 -29 -70 -61 // -28 -67 -96 -27 -91 -67
流的基本操作规律
- 转换流
InputStreamReader:字节流到字符流的桥梁。解码。 OutputStreamWriter:字符到字节的桥梁。编码。
- 流的操作规律
1、明确源和目的 源:InputStream Reader 目的:OutputStream Writer 2、明确数据是否是纯文本数据 源:是纯文本:Reader 否:InputStream 目的:是纯文本:Writer 否:OutputStream 3、明确具体的设备 源设备: 硬盘:File 键盘:System.in 内存:数组 网络:Socket流 目的设备: 硬盘:File 控制台:System.out 内存:数组 网络:Socket流 4、是否需要其他额外功能 是否需要高效(缓冲区):是,就加上Buffer 是否需要转换:是...
- 什么时候使用转换流?
1. 源或者目的对应的设备是字节流,但是操作的却是文本数据,可以使用转换流作为桥梁。提高对文本操作的便捷。 2. 一旦操作文本涉及到具体的指定的编码表时,必须使用转换流。
- 转换流的编码解码
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("gbk.txt"), "gbk"); FileWriter fw = new FileWriter("gbk.txt"); //这两句代码功能是相同的
FileWriter其实就是转换流指定了本地默认码表的体现。而且是这个转换流的子类对象,可以方便操作文本文件 简单说:操作文件的字节流+本机默认的编码表,这是按照默认码表来操作文件的便捷类 如果操作文本文件需要明确具体的编码,FileWriter就不行了,必须用转换流 注意:如果明确指定了编码表的动作,那就不可以使用FileWriter,因为FileWriter内部是使用默认的本地码表,只能使用其父类OutputStreamWriter。 OutputStreamWriter接收一个字节流对象,既然是操作文件,那么该对象应该是FileOutputStream
public class Test { public static void main(String[] args) { File file = new File("e:\\demo.txt"); try { writeFile(file, "你好" + System.lineSeparator() + "安卓", "utf-8"); readFile(file, "gbk"); readFile(file, "utf-8"); } catch (IOException e) { e.printStackTrace(); } } private static void readFile(File file, String code) throws IOException { BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(file), code)); String line = null; while ((line = reader.readLine()) != null) { System.out.println(line); } reader.close(); } private static void writeFile(File file, String in, String code) throws IOException { BufferedWriter writer = new BufferedWriter(new OutputStreamWriter( new FileOutputStream(file), code)); writer.write(in); writer.close(); } } /**输出: 浣犲ソ 瀹夊崜 你好 安卓 */