java的io流(同步阻塞式io流)
1.io流简介
不论是Reader,Writer,还是InputStream,OutputStream,在创建相应的对象是只是创建了相应的映射,相当于修了一条马路通向两个位置,但是本身并不参与数据的传输,数据的传输是通过数组完成的,这个传输的过程是单向的(nio的buffer是双向的)面向于流的传输(nio面向缓存数据块),对于读的时候不论基于单个字符还是基于数组,当没有可读的元素的时候返回值都是-1,有可读的时候返回的是有效数据的字节或字符长度,返回字符串的时候,在没有的情况下为null,对于一个输入流来说具有skip的方法,跳到我们制定的地方去开始输入,对于写我们可以设置为true在尾部添加,对于覆盖数据我们可以是用RandomAccessFile的seek设定覆盖的位置,对于我们对象流(序列化流)可以将一个文件保存在一个文件中,然后在另一个地方读取(读取的前提条件是相应的序列化类需要已经加载到JVM中),对于BufferedOutputStream等采用装饰模式,也就是在FileOutputStream外面包了一层,对于文件的乱码问题前面有一篇有介绍。
2.file
public class CreateFile { // 创建文件 public static void creatFile(String filePath) throws Exception { File file = new File(filePath); if (!file.exists()) { file.createNewFile(); } else { System.err.println("文件夹以及存在"); } } // 创建文件夹 public static void creatFolder(String filePath) { File file = new File(filePath); if (!file.exists()) { file.mkdirs(); } else { System.err.println("文件夹以及存在"); } } // 在指定的文件下搜索文件(可以模糊查找) public static List<String> FuzzySearch(String filePath, String regex) { LinkedList<String> lls = new LinkedList<>(); regex = ".*" + regex + ".*"; File file = new File(filePath); if (!file.exists()) { System.err.println("指定的目录不存在"); return null; } if (!file.isDirectory()) { System.err.println("指定的不是目录"); return null; } getErgodicFiles(regex, lls, file); if (lls.size() == 0) { System.out.println("没有找到符合的信息"); } return lls; } // 遍历文件 public static void getErgodicFiles(String regex, LinkedList<String> lls, File file) { if (file.isDirectory()) { File[] lfs = file.listFiles(); for (File f : lfs) { if (!f.isDirectory()) { String absolutePath = f.getAbsolutePath(); if (absolutePath.matches(regex)) { lls.add(absolutePath); } } else { getErgodicFiles(regex, lls, f); } } } } // 遍历文件 public static void getErgodicFiles(String fileName, File file) { if (file.isDirectory()) { File[] lfs = file.listFiles(); for (File f : lfs) { if (!f.isDirectory()) { f.delete(); } else { getErgodicFiles(fileName, f); } } } } public static void delete(String fileName) { File file = getFile(fileName); if (file == null) { return; } if (!file.isDirectory()) { file.delete(); return; } getErgodicFiles(fileName, file); file.delete(); System.out.println("删除成功"); } // 设置文件只读,但是可以另存为 public static void setOnlyRead(String fileName) { File file = getFile(fileName); if (file == null) { return; } file.setReadable(true); file.setWritable(false); } private static File getFile(String fileName) { File file = new File(fileName); if (!file.exists()) { System.err.println("指定的目录或者文件夹不存在不存在"); return null; } return file; } public static void main(String[] args) throws Exception { // CreateFile.creatFile("F:/test/file"); // CreateFile.creatFolder("F:/test/file1.txt"); // List<String> fuzzySearch = CreateFile.FuzzySearch("F:/test", "file"); // System.out.println(fuzzySearch); // CreateFile.delete("F:/test/file1.txt"); // CreateFile.setOnlyRead("F:/test/file1/file.txt"); } }
3.new FileOutputStream与 new RandomAccessFile的区别
一个存在则新建,一个存在则覆盖覆盖,默认的seek是从0开始的,RandomAccessFile对同一文件可进行读写
4.更改某一个文件中的值然后保存
public static void main(String[] args) { try { InputStream resourceAsStream4 = PopertiesDemo1.class.getClassLoader() .getResourceAsStream("cn/collection/demo/config.properties"); Properties properties = new Properties(); properties.load(resourceAsStream4); System.out.println(properties.getProperty("name")); properties.setProperty("name", "李四"); System.out.println(properties.getProperty("name")); FileWriter fileWriter = new FileWriter("config1"); // "aa" 描述信息 properties.store(fileWriter, "aa"); fileWriter.close(); } catch (Exception e) { System.out.println("没有找到文件"); } }
5.对象流
实现Externalizable接口,Externalizable继承了Serializable 接口,Externalizable中有两个方法需要重写writeExternal及readExternal,在writeObject和readObject时会调用相应的方法。
transient关键字表示瞬态的,在保存的是是后不会被保存进对象流,假如我么依旧添加,那么可以使用如下方法
public class Person implements Serializable { private String adress; // transient 关键字 表示瞬态 假如需要保存这个那么需要单独的去保存 private transient int age; private static String name; private transient static int id; public String getAdress() { return adress; } public void setAdress(String adress) { this.adress = adress; } public static int getId() { return id; } public void setId(int id) { this.id = id; } public Person() { super(); } public Person(int age, String adress, int id, String name) { super(); this.age = age; this.adress = adress; this.id = id; this.name = name; } public static String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } // 一定要为私有才可以被调用 private void writeObject(ObjectOutputStream stream) throws IOException { // 将非静态的非瞬态的保存在对象流中 stream.defaultWriteObject(); stream.writeObject(age); stream.close(); } // 一定要为私有才可以被调用 private void readObject(ObjectInputStream stream) throws ClassNotFoundException, IOException {
stream.defaultReadObject(); age = (int) (stream.readObject()); stream.close(); } @Override public String toString() { return "Person [age=" + age + ", adress=" + adress + ",name=" + name + ",id=" + id + "]"; } }
6.分段读取文件,每次只保存一部分(网络版的在爬虫中)
public class SegmentedReadFile extends Thread { private volatile boolean flag = false; @Override public void run() { try { Scanner scanner = new Scanner(System.in); String nextLine = scanner.nextLine(); if (nextLine.equals("true")) { this.flag = true; } } catch (Exception e) { } } public boolean test(String src, String target) throws IOException { File file = new File(src); File file2 = new File(target); // 这里以单个文件为例 if (file.isDirectory()) { System.out.println("该路径是文件夹不是文件"); return false; } if (!file.isFile()) { System.out.println("该文件路径不存在"); return false; } if (!file2.isFile()) { try { file2.createNewFile(); } catch (IOException e) { return false; } } FileInputStream fileInputStream=null; BufferedInputStream bufferedInputStream=null; FileOutputStream fileOutputStream=null; BufferedOutputStream bufferedOutputStream=null; if (file2.isFile()) { long lg1 = file.length(); int segment = 24000000; fileInputStream = new FileInputStream(file); bufferedInputStream = new BufferedInputStream(fileInputStream); fileOutputStream = new FileOutputStream(file2, true); bufferedOutputStream = new BufferedOutputStream(fileOutputStream); byte[] bys = new byte[1024]; if (file.length() - file2.length() >= segment) { long lg = file2.length(); bufferedInputStream.skip(lg); for (int i = 0; i <= segment / 1024; i++) { if (flag) { break; }
bufferedInputStream.read(bys); if (i < segment / 1024 ) { bufferedOutputStream.write(bys, 0, 1024); } else { bufferedOutputStream.write(bys, 0, segment%1024); } } } else if(file.length() - file2.length()>0){ long lg = file2.length(); bufferedInputStream.skip(lg); long lastSize=file.length() - file2.length(); for (int i = 0; i <= lastSize / 1024; i++) { if (flag) { break; } int read = bufferedInputStream.read(bys); if (read != -1) { bufferedOutputStream.write(bys, 0, read); } } }else{ System.out.println("传输完成"); } } bufferedInputStream.close(); bufferedOutputStream.close(); System.gc(); System.runFinalization(); return true; } public static void main(String[] args) throws IOException { SegmentedReadFile segmentedReadFile = new SegmentedReadFile(); segmentedReadFile.setDaemon(true); segmentedReadFile.start(); boolean test = segmentedReadFile.test("G:/360安全浏览器下载安装包/tim_pc.exe", "G:/360安全浏览器下载安装包/tim_pc1.exe"); if (!test) { System.out.println("传输失败"); } } }
7.重定向输出记录错误日志文件
public class Redirect1 { public static void main(String[] args) throws FileNotFoundException { String str="hello world"; PrintStream printStream = new PrintStream("y.txt");
//可以不关闭,自动会刷新缓存 printStream.print(str); }
8.字节字符转换流
public static void main(String[] args) throws IOException { //方式一 FileInputStream fileInputStream = new FileInputStream("1.txt"); //不乱码的前提是知道编码,或者是unicode码的\\u方式写的 InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream,"utf-8"); BufferedReader bufferedReader = new BufferedReader(inputStreamReader); //java内存中是使用unicode码保存的 String readLine = bufferedReader.readLine(); System.out.println(readLine); if(bufferedReader!=null){ bufferedReader.close(); } if(inputStreamReader!=null){ inputStreamReader.close(); } if(fileInputStream!=null){ fileInputStream.close(); } FileOutputStream fileOutputStream = new FileOutputStream("3.txt"); OutputStreamWriter outputStreamWriter = new OutputStreamWriter(fileOutputStream,"gbk"); BufferedWriter bufferedWriter = new BufferedWriter(outputStreamWriter); bufferedWriter.write(readLine); if(bufferedWriter!=null){ bufferedWriter.close(); } if(outputStreamWriter!=null){ outputStreamWriter.close(); } if(fileOutputStream!=null){ fileOutputStream.close(); } FileInputStream fileInputStream1 = new FileInputStream("3.txt"); //按指定解码然后按unicode保存 InputStreamReader inputStreamReader1 = new InputStreamReader(fileInputStream1,"gbk"); BufferedReader bufferedReader1 = new BufferedReader(inputStreamReader1); String readLine1 = bufferedReader1.readLine(); //将unicode码有转换成了工作空间相应的编码 System.out.println(readLine1); if(bufferedReader1!=null){ bufferedReader1.close(); } if(inputStreamReader1!=null){ inputStreamReader1.close(); } if(fileInputStream1!=null){ fileInputStream1.close(); } //方式二 ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); byteArrayOutputStream.write(readLine1.getBytes()); //因为我的工作空间是utf-8的 String string = byteArrayOutputStream.toString("utf-8"); byteArrayOutputStream.close(); System.out.println(string); FileInputStream fileInputStream2 = new FileInputStream("3.txt"); ByteArrayOutputStream byteArrayOutputStream2 = new ByteArrayOutputStream(); byte [] bs =new byte [1024]; int len =0; while((len=fileInputStream2.read(bs))!=-1){ byteArrayOutputStream2.write(bs, 0, len); } //不会乱码 String string2 = byteArrayOutputStream2.toString("gbk"); fileInputStream2.close(); byteArrayOutputStream2.close(); System.out.println(string2); //readLine.getBytes(charset) //Charset.forName("UTF-8").encode(str) }
9.其他一些流
SequenceInputStream 合并多个流文件 SequenceInputStream(Enumeration<? extends InputStream> e)
PrintWriter 与 PrintStream 差不多
PipedWriter 是向与其它线程共用的管道中写入数据
CharArrayWriter、StringWriter 是两种基本的介质流,它们分别向Char 数组、String 中写入数据
DataOutputStream 保存相应的数据,按保存的顺序读取
ZipOutputStream 压缩流 批量压缩(文件夹)可以使用这个方法putNextEntry(ZipEntry e),
ZipEntry(String name)
使用指定名称创建新的 ZIP 条目。
ZipInputStream 解压流
public class ZipInputStreamDemo2 { public static void main(String[] args) throws IOException { File file = new File("d:" + File.separator + "zipFile.zip"); File outFile = null; ZipFile zipFile = new ZipFile(file); ZipInputStream zipInput = new ZipInputStream(new FileInputStream(file)); ZipEntry entry = null; InputStream input = null; OutputStream output = null; while ((entry = zipInput.getNextEntry()) != null) { System.out.println("解压缩" + entry.getName() + "文件"); outFile = new File("d:" + File.separator + entry.getName()); if (!outFile.getParentFile().exists()) { outFile.getParentFile().mkdir(); } if (!outFile.exists()) { outFile.createNewFile(); } input = zipFile.getInputStream(entry); output = new FileOutputStream(outFile); int temp = 0; while ((temp = input.read()) != -1) { output.write(temp); } input.close(); output.close(); } } }
//多个文件进行压缩
public class ZipOutputStreamDemo2 { public static void main(String[] args) throws IOException { // 要被压缩的文件夹 File file = new File("d:" + File.separator + "temp"); File zipFile = new File("d:" + File.separator + "zipFile.zip"); InputStream input = null; ZipOutputStream zipOut = new ZipOutputStream(new FileOutputStream(zipFile)); zipOut.setComment("hello"); if (file.isDirectory()) { File[] files = file.listFiles(); for (int i = 0; i < files.length; ++i) { input = new FileInputStream(files[i]); zipOut.putNextEntry(new ZipEntry(file.getName() + File.separator + files[i].getName())); int temp = 0; while ((temp = input.read()) != -1) { zipOut.write(temp); } input.close(); } } } }