首页 / JAVA / java io流(1)
java io流(1)
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了java io流(1),小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含12609字,纯文字阅读大概需要19分钟。
内容图文
![java io流(1)](/upload/InfoBanner/zyjiaocheng/625/0a5f4b31e2764f83854a33d555ba5cbf.jpg)
![java io流(1) - 文章图片](/upload/getfiles/0001/2021/5/1/20210501034159188.jpg)
![java io流(1) - 文章图片](/upload/getfiles/0001/2021/5/1/20210501034159563.jpg)
![java io流(1) - 文章图片](/upload/getfiles/0001/2021/5/1/20210501034200004.jpg)
1 // 简单实现复制 2 public static void main(String[] args) throws IOException { 3 //1,读取一个已有的文本文件,使用字符读取流和文件相关联。 4 FileReader fr = new FileReader("IO流_2.txt"); 5 //2,创建一个目的,用于存储读到数据。 6 FileWriter fw = new FileWriter("copytext_1.txt"); 7 //3,频繁的读写操作。 8 int ch = 0; 9 while((ch=fr.read())!=-1){ 10 fw.write(ch); 11 } 12 //4,关闭流资源。 13 fw.close(); 14 fr.close(); 15 } 16 17 // 引入缓冲做复制优化 手动定义缓冲去 18 // 引入字符数组作为缓冲区:(循环次数小,效率高) 19 private static final int BUFFER_SIZE = 1024; 20 public static void main(String[] args) { 21 FileReader fr = null; 22 FileWriter fw = null; 23 try { 24 fr = new FileReader("IO流_2.txt"); 25 fw = new FileWriter("copytest_2.txt"); 26 //创建一个临时容器,用于缓存读取到的字符。 27 char[] buf = new char[BUFFER_SIZE];//这就是缓冲区。 28 //定义一个变量记录读取到的字符数,(其实就是往数组里装的字符个数) 29 int len = 0; 30 while((len=fr.read(buf))!=-1){ 31 fw.write(buf, 0, len); 32 } 33 } catch (Exception e) { 34 // System.out.println("读写失败"); 35 throw new RuntimeException("读写失败"); 36 }finally{ 37 if(fw!=null) 38 try { 39 fw.close(); 40 } catch (IOException e) { 41 42 e.printStackTrace(); 43 } 44 if(fr!=null) 45 try { 46 fr.close(); 47 } catch (IOException e) { 48 49 e.printStackTrace(); 50 } 51 } 52 } 53 54 // 优化三:使用装饰者模式添加上缓冲区功能 55 public static void main(String[] args) throws IOException { 56 FileReader fr = new FileReader("buf.txt"); 57 // 装饰上缓冲区功能 58 BufferedReader bufr = new BufferedReader(fr); 59 60 FileWriter fw = new FileWriter("buf_copy.txt"); 61 BufferedWriter bufw = new BufferedWriter(fw); 62 63 String line = null; 64 while((line=bufr.readLine())!=null){ 65 bufw.write(line); 66 bufw.newLine(); 67 bufw.flush(); 68 } 69 /* 70 int ch = 0; 71 while((ch=bufr.read())!=-1){ 72 bufw.write(ch); 73 } 74 */ 75 bufw.close(); 76 bufr.close(); 77 }
? 所以引入BufferWriter(缓冲区的出现提高了对数据的读写效率,缓冲区要结合流才可以使用,在流的基础上对流的功能进行了增强) ? 多层装饰强化:
InputStream input = new GZIPInputStream( // 第二层装饰 new BufferedInputStream( // 第一层装饰 new FileInputStream("test.gz") // 核心功能 ));
GZip常用于linux环境下,是一种非常简单的压缩算法: GZIPOutputStream类用于压缩 GZIPInputStream类用于解压缩
// 压缩 ByteArrayOutputStream out = new ByteArrayOutputStream(); gzip = new GZIPOutputStream(out); gzip.write(str.getBytes(encoding)); // 解压缩 byte[] uncompress(byte[] bytes) { if (bytes == null || bytes.length == 0) { return null; } ByteArrayOutputStream out = new ByteArrayOutputStream(); ByteArrayInputStream in = new ByteArrayInputStream(bytes); try { GZIPInputStream ungzip = new GZIPInputStream(in); byte[] buffer = new byte[256]; int n; while ((n = ungzip.read(buffer)) >= 0) { out.write(buffer, 0, n); } } catch (IOException e) { ApiLogger.error("gzip uncompress error.", e); } return out.toByteArray(); }
File对象来操作文件和目录。
new File("/usr/bin/javac"); // Windows平台使用\作为路径分隔符,在Java字符串中需要用\\表示一个\。Linux平台使用/作为路径分隔符: // 传先对路径,假设当前java文件目录是C:\Docs File f1 = new File("sub\\javac"); // 绝对路径是C:\Docs\sub\javac File f3 = new File(".\\sub\\javac"); // 绝对路径是C:\Docs\sub\javac File f3 = new File("..\\sub\\javac"); // 绝对路径是C:\sub\javac
? Path对象和File对象类似,但操作更加简单:如果需要对目录进行复杂的拼接、遍历等操作,使用Path对象更方便。 ? read()方法是阻塞(Blocking)的,因为读取IO流相比执行普通代码,速度会慢很多,因此,无法确定read()方法调用到底要花费多长时间。
int n; n = input.read(); // 必须等待read()方法返回才能执行下一行代码 int m = n用FileInputStream可以从文件获取输入流,这是InputStream常用的一个实现类。此外,ByteArrayInputStream可以在内存中模拟一个InputStream:
public static void main(String[] args) throws IOException { byte[] data = { 72, 101, 108, 108, 111, 33 }; try (InputStream input = new ByteArrayInputStream(data)) { int n; while ((n = input.read()) != -1) { System.out.println((char)n); } } }
? OutputStream void write(int b) 虽然传入的是int参数,但只会写入一个字节,即只写入int最低8位表示字节的部分(相当于b & 0xff) OutputStream还提供了一个flush()方法,它的目的是将缓冲区的内容真正输出到目的地。(通常情况下,我们不需要调用这个flush()方法,因为缓冲区写满了OutputStream会自动调用它,要是输入的不能把缓冲区填满,就需要手动输出目的地了)
// write()方法也是阻塞 OutputStream output = new FileOutputStream("out/readme.txt"); output.write("Hello".getBytes("UTF-8")); // Hello output.close();
InputStream根据来源可以包括: FileInputStream:从文件读取数据,是最终数据源; ServletInputStream:从HTTP请求读取数据,是最终数据源; Socket.getInputStream():从TCP连接读取数据,是最终数据源; ... IO Filter模式(为InputStream和OutputStream增加功能) 可以把一个InputStream和任意个FilterInputStream组合; 可以把一个OutputStream和任意个FilterOutputStream组合, Filter模式可以在运行期动态增加功能(又称Decorator模式)。 如果要给FileInputStream添加缓冲和签名的功能,那么我们还需要派生BufferedDigestFileInputStream。如果要给FileInputStream添加缓冲和加解密的功能,则需要派生BufferedCipherFileInputStream。如下
BufferedFileInputStream extends FileInputStream DigestFileInputStream extends FileInputStream CipherFileInputStream extends FileInputStreamZipInputStream是一种FilterInputStream,另一个JarInputStream是从ZipInputStream派生,它增加的主要功能是直接读取jar文件里面的MANIFEST.MF文件。因为本质上jar包就是zip包,只是额外附加了一些固定的描述文件。 ? 在classpath中的资源文件,路径总是以/开头,我们先获取当前的Class对象,然后调用getResourceAsStream()就可以直接从classpath读取任意的资源文件:
// 如果资源文件不存在,input则为null try (InputStream input = getClass().getResourceAsStream("/default.properties")) { if (input != null) { // TODO: } }
把默认的配置放到jar包中,再从外部文件系统读取一个可选的配置文件,就可以做到既有默认的配置文件,又可以让用户自己修改配置:
Properties props = new Properties(); props.load(inputStreamFromClassPath("/default.properties")); props.load(inputStreamFromFile("./conf.properties"));
对象序列化: 把一个Java对象变为byte[]数组,需要使用ObjectOutputStream。它负责把一个Java对象写入一个字节流:
static <T extends Serializable> T clone(T obj) { T cloneObj = null; try { // 写入字节流 ByteArrayOutputStream bo = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(bo); oos.writeObject(obj); oos.close(); // 分配内存,写入原始对象,生成新对象 ByteArrayInputStream bi = new ByteArrayInputStream(bo.toByteArray());//获取上面的输出字节流 ObjectInputStream oi = new ObjectInputStream(bi); // 返回生成的新对象 cloneObj = (T) oi.readObject(); oi.close(); } catch (Exception e) { e.printStackTrace(); } return cloneObj; }
Windows系统的默认编码可能是GBK,打开一个UTF-8编码的文本文件就会出现乱码。 要避免乱码问题,我们需要在创建FileReader时指定编码: Reader reader = new FileReader("src/readme.txt", StandardCharsets.UTF_8); ? CharArrayReader可以在内存中模拟一个Reader,它的作用实际上是把一个char[]数组变成一个Reader,这和ByteArrayInputStream非常类似: try (Reader reader = new CharArrayReader("Hello".toCharArray())) {} StringReader可以直接把String作为数据源,它和CharArrayReader几乎一样: try (Reader reader = new StringReader("Hello")) {} ? ? Reader和InputStream有什么关系? FileReader实现了文件字符流输入,使用时需要指定编码; 除了特殊的CharArrayReader和StringReader,普通的Reader实际上是基于InputStream构造的,因为Reader需要从InputStream中读入字节流(byte),然后,根据编码设置,再转换为char就可以实现字符流。如果我们查看FileReader的源码,它在内部实际上持有一个FileInputStream。 ? 既然Reader本质上是一个基于InputStream的byte到char的转换器,那么,如果我们已经有一个InputStream,想把它转换为Reader,是完全可行的。InputStreamReader就是这样一个转换器,它可以把任何InputStream转换为Reader。示例代码如下:
// 构造InputStreamReader时,我们需要传入InputStream, // 还需要指定编码,就可以得到一个Reader对象 // 关闭对象时,只需要关闭最外层的Reader对象即可(它会在内部自动调用InputStream的close()方法) try (Reader reader = new InputStreamReader(new FileInputStream("src/readme.txt"), "UTF-8")) { // TODO: }
? OutputStream? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?Writer 字节流,以byte为单位? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?字符流,以char为单位 写入字节(0~255):void write(int b) 写入字符(0~65535):void write(int c) 写入字节数组:void write(byte[] b) 写入字符数组:void write(char[] c) 无对应方法 写入String:void write(String s) ?
try (Writer writer = new FileWriter("readme.txt", StandardCharsets.UTF_8)) { writer.write('H'); // 写入单个字符 writer.write("Hello".toCharArray()); // 写入char[] writer.write("Hello"); // 写入String }
? java IO包装流如何关闭? 如下例子代码:
如下例子代码: FileInputStream is = new FileInputStream("."); BufferedInputStream bis = new BufferedInputStream(is); bis.close(); 从设计模式上看: java.io.BufferedInputStream是java.io.InputStream的装饰类。 BufferedInputStream装饰一个 InputStream 使之具有缓冲功能, is要关闭只需要调用最终被装饰出的对象的 close()方法即可, 因为它最终会调用真正数据源对象的 close()方法。 BufferedInputStream的close方法中对InputStream进行了关闭, 下面是jdk中附带的源代码: java.io.BufferedInputStream的api: close public void close()throws IOException 关闭此输入流并释放与该流关联的所有系统资源。 如果不想用上述方式关闭流:可以逐层关闭,主要最外层的先关闭### 如下例子: public static void main(String[] args) throws Exception { FileOutputStream fos = new FileOutputStream("d:\\a.txt"); OutputStreamWriter osw = new OutputStreamWriter(fos, "UTF-8"); BufferedWriter bw = new BufferedWriter(osw); bw.write("java IO close test"); //从内带外顺序顺序会报异常 fos.close(); osw.close(); bw.close(); } 报出异常: Exception in thread "main" java.io.IOException: Stream closed at sun.nio.cs.StreamEncoder.ensureOpen(StreamEncoder.java:26) at sun.nio.cs.StreamEncoder.write(StreamEncoder.java:99) at java.io.OutputStreamWriter.write(OutputStreamWriter.java:190) at java.io.BufferedWriter.flushBuffer(BufferedWriter.java:111) at java.io.BufferedWriter.close(BufferedWriter.java:246) at com.my.test.QQ.main(QQ.java:22) 如下例子: public static void main(String[] args) throws Exception { FileOutputStream fos = new FileOutputStream("d:\\a.txt"); OutputStreamWriter osw = new OutputStreamWriter(fos, "UTF-8"); BufferedWriter bw = new BufferedWriter(osw); bw.write("java IO close test"); // 从外到内顺序关闭ok bw.close(); osw.close(); fos.close(); } 验证ok
下面的流是装饰流对其他流进行强化
![java io流(1) - 文章图片](/upload/getfiles/0001/2021/5/1/20210501034200595.jpg)
![java io流(1) - 文章图片](/upload/getfiles/0001/2021/5/1/20210501034200925.jpg)
![java io流(1) - 文章图片](/upload/getfiles/0001/2021/5/1/20210501034201408.jpg)
内容总结
以上是互联网集市为您收集整理的java io流(1)全部内容,希望文章能够帮你解决java io流(1)所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。