字节流

字符流:

  1. FileReader
  2. FileWriter
  3. BufferedReader
  4. BufferedWriter

字节流:

  1. FileInputStream
  2. FileOutputStream
  3. BufferedInputStream
  4. BufferedOutputStream

想要操作图片数据,这时就要用到字节流。

示例代码如下:

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;public class FileOutputStreamDemo0 {public static void main(String[] args) throws IOException {//writeFile();//readFile();//readFile_2();
        readFile_3();}public static void readFile_3() throws IOException {FileInputStream fis = new FileInputStream("fos.txt");//int num = fis.available();byte[] buf = new byte[fis.available()];//定义一个刚刚好的缓冲区,不用在循环了。不过慎用!!!
        fis.read(buf);//System.out.println("num = " + num);System.out.println(new String(buf));fis.close();}public static void readFile_2() throws IOException {FileInputStream fis = new FileInputStream("fos.txt");byte[] buf = new byte[1024];//还是建议使用1024的整数倍开辟字节数组int len = 0;while((len = fis.read(buf)) != -1) {System.out.println(new String(buf, 0, len));}fis.close();}public static void readFile() throws IOException {FileInputStream fis = new FileInputStream("fos.txt");int ch = 0;while((ch = fis.read()) != -1) {System.out.println((char) ch);}fis.close();}public static void writeFile() throws IOException {FileOutputStream fos = new FileOutputStream("fos.txt");fos.write("abcde".getBytes());fos.close();}}

练习1:复制一个图片。

思路:

  1. 用字节读取流对象和图片关联。
  2. 用字节写入流对象创建一个图片文件,用于存储获取到的图片数据。
  3. 通过循环读写,完成数据的存储。
  4. 关闭资源。

代码:

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;public class CopyPic {public static void main(String[] args) {FileOutputStream fos = null;FileInputStream fis = null;try {fos = new FileOutputStream("E:\\MyJava\\workspace\\IO_Project\\Krystal.jpg");fis = new FileInputStream("D:\\Krystal.jpg");byte[] buf = new byte[1024];int len = 0;while((len = fis.read(buf)) != -1) {fos.write(buf, 0, len);}} catch (IOException e) {throw new RuntimeException("复制失败!");} finally {try {if(fis != null) fis.close();} catch (IOException e) {throw new RuntimeException("读取关闭失败!");}try {if(fos != null) fos.close();} catch (IOException e) {throw new RuntimeException("写入关闭失败!");}}}}

练习2:复制一个MP3文件。

通过缓冲区(BufferedOutputStream/BufferedInputStream),演示MP3的复制。

代码:

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;public class CopyMp3 {public static void main(String[] args) throws IOException {long start = System.currentTimeMillis();copy_2();long end = System.currentTimeMillis();System.out.println((end - start) + "毫秒");}/** 通过字节流的缓冲区完成复制*/public static void copy_1() throws IOException {BufferedInputStream bufis = new BufferedInputStream(new FileInputStream("E:\\KuGou\\Temp\\滨琦步 - 犬夜叉主题曲.mp3"));BufferedOutputStream bufos = new BufferedOutputStream(new FileOutputStream("E:\\MyJava\\workspace\\IO_Project\\滨琦步 - 犬夜叉主题曲.mp3"));int by = 0;while((by = bufis.read()) != -1) {bufos.write(by);}bufis.close();bufos.close();}}

练习3:自定义一个类模拟BufferedInputStream,完成一个MP3文件的复制。

分析:

mp3是由二进制数据组成的:
11111111-1110000000000000000000101010110111010111010010110001问题:自定义的myRead()函数为什么会返回int类型,而不直接返回byte类型呢?
分析:
byte: -1  ----> int: -111111111(-1)提升为11111111 11111111 11111111 11111111(-1)
11111111(-1)--->提升为一个int类型,那还不是-1吗?是-1的原因是因为在8个1前面补的都是1导致的。
那么我只要在前面补0,即可以保留原字节数据不变,又可以避免-1的出现。
怎么补0呢?11111111 11111111 11111111 11111111
&   00000000 00000000 00000000 11111111
------------------------------------------00000000 00000000 00000000 11111111所以应把11111111(-1)提升为00000000 00000000 00000000 11111111(255),避免返回-1这种情况

代码:

import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;class MyBufferedInputStream {private InputStream in;private byte[] buf = new byte[1024 * 4];private int pos = 0, count = 0;MyBufferedInputStream(InputStream in) {this.in = in;}/** 一次读一个字节,从缓冲区(字节数组)获取。*/public int myRead() throws IOException {/** 通过in对象读取硬盘上数据,并存储到buf中。*/if(count == 0) {count = in.read(buf);if(count < 0)return -1;pos = 0;byte b = buf[pos];count--;pos++;return b & 255;} else if(count > 0) {byte b = buf[pos];count--;pos++;return b & 0xff;}return -1;}public void myClose() throws IOException {in.close();}
}
public class MyBufferedInputStreamDemo {public static void main(String[] args) throws IOException {long start = System.currentTimeMillis();copy_2();long end = System.currentTimeMillis();System.out.println((end - start) + "毫秒");}public static void copy_2() throws IOException {MyBufferedInputStream bufis = new MyBufferedInputStream(new FileInputStream("E:\\KuGou\\Temp\\滨琦步 - 犬夜叉主题曲.mp3"));BufferedOutputStream bufos = new BufferedOutputStream(new FileOutputStream("E:\\MyJava\\workspace\\IO_Project\\滨琦步 - 犬夜叉主题曲_2.mp3"));int by = 0;//System.out.println("第一个字节:" + bufis.myRead());//第一个字节:-1,因为读到了连续的11111111while((by = bufis.myRead()) != -1) {bufos.write(by);}bufis.myClose();bufos.close();}}

System类对IO的支持

读取键盘录入。

System.out:对应的是标准输出设备,控制台。

System.in:对应的是标准输入设备,键盘。

例,需求:通过键盘录入数据。当录入一行数据后,就将该行数据进行打印。如果录入的数据是over,那么录入停止。

代码:

import java.io.IOException;
import java.io.InputStream;public class ReadIn {public static void main(String[] args) throws IOException {InputStream in = System.in;StringBuilder sb = new StringBuilder();while(true) {int ch = in.read();if(ch == '\r')continue;if(ch == '\n') {String s = sb.toString();if("over".equals(s))break;System.out.println(s.toUpperCase());sb.delete(0, sb.length());//清空缓冲区} else {sb.append((char) ch);}}//System.out.println('\r' + 0);//13//System.out.println('\n' + 0);//10/*int by = in.read();int by1 = in.read();int by2 = in.read();System.out.println(by);System.out.println(by1);System.out.println(by2);*/}
}

通过刚才的键盘录入一行数据并打印其大写,发现其实就是读一行数据的原理。也就是readLine()方法。

能不能直接使用readLine()方法来完成键盘录入的一行数据的读取呢?

readLine()方法是字符流BufferedReader类中的方法,而键盘录入的read()方法是字节流InputStream的方法,那么能不能将字节流转成字符流,再使用字符流缓冲区的readLine()方法呢?

此时就需要用到转换流。

转换流:

  1. InputStreamReader字节流通向字符流的桥梁:它使用指定的charset读取字节并将其解码为字符。它使用的字符集可以由名称指定或显式给定,或者可以接受平台默认的字符集(GBK)
  2. OutputStreamWriter字符流通向字节流的桥梁:可使用指定的charset将要写入流中的字符编码成字节。它使用的字符集可以由名称指定或显式给定,否则将接受平台默认的字符集。

上例优化之后的代码为:

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;public class TransStreamDemo0 {public static void main(String[] args) throws IOException {/** 获取键盘录入对象。*///InputStream in = System.in;/** 将字节流对象转成字符流对象,使用转换流——InputStreamReader*///InputStreamReader isr = new InputStreamReader(in);/** 为了提高效率,将字符流进行缓冲区技术高效操作,使用BufferedReader*///BufferedReader bufr = new BufferedReader(isr);/** 简写格式,键盘录入最常见写法*/BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));//OutputStream out = System.out;//屏幕输出/** 字符流输出对象转换成字节流输出对象*///OutputStreamWriter osw = new OutputStreamWriter(out);//BufferedWriter bufw = new BufferedWriter(osw);/** 简写格式*/BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(System.out));String str = null;while((str = bufr.readLine()) != null) {if("over".equals(str))break;//System.out.println(str.toUpperCase());
            bufw.write(str.toUpperCase());bufw.newLine();bufw.flush();}bufw.close();//并没有写bufr.close();是因为此程序一结束掉,就给关闭了。
    }}

流操作的基本规律

最痛苦的就是流对象有很多,不知道该用哪一个。

通过三个明确来完成:

  1、明确源和目的。

    源:输入流。InputStream Reader

    目的:输出流。OutputStream Writer

  2、操作的数据是否是纯文本。

    是:字符流。

    不是:字节流。

  3、当体系明确后,在明确要使用哪个具体的对象。

    通过设备来进行区分:

    源设备:内存、硬盘、键盘。

    目的设备:内存、硬盘、控制台。

例1、需求:将一个文本文件中的数据存储到另一个文件中。(复制文件)

  分析:

    源:因为是源,所以使用读取流。InputStream Reader

    是不是操作文本文件?

    是!这时就可以选择Reader,这样体系就明确了。

    接下来要明确要使用该体系中的那个对象?

    明确设备:硬盘上的一个文件。Reader体系中可以操作文件的对象是FileReader。

    是否需要提高效率?是!加入Reader体系中的缓冲区BufferedReader。

FileReader fr = new FileReader("a.txt");
BufferedReader bufr = new BufferedReader(fr);

    目的:OutputStream Writer

    目的是否是纯文本?是!Writer。

    设备:硬盘上的一个文件。

    Writer体系中可以操作文件的对象是FileWriter。

    是否需要提高效率?是!加入Reader体系中的缓冲区BufferedWriter。

FileWriter fw = new FileWriter("b.txt");
BufferedWriter bufw = new BufferedWriter(fr);

练习:将一个图片文件中的数据存储到另一个文件中。(复制文件)

代码:

/** 练习:将一个图片文件中的数据存储到另一个文件中。(复制文件)*/
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;public class test0 {public static void main(String[] args) {FileInputStream fis = null;FileOutputStream fos = null;BufferedInputStream bis = null;BufferedOutputStream bos = null;byte[] by = new byte[1024];int len = 0;try {fis = new FileInputStream("d:\\Krystal.jpg");bis = new BufferedInputStream(fis);fos = new FileOutputStream("d:\\java\\io123\\Krystal.jpg");bos = new BufferedOutputStream(fos);while((len = bis.read(by)) != -1) {bos.write(by, 0, len);}}  catch (IOException e) {throw new RuntimeException("图片复制失败!");} finally {try {if(bis != null) bis.close();} catch (IOException e) {throw new RuntimeException("关闭读取流失败!");}try {if(bos != null) bos.close();} catch (IOException e) {throw new RuntimeException("关闭写入流失败!");}}}}

例2、需求:将键盘录入的数据保存到一个文件中。

  分析:

    这个需求中有源和目的都存在。那么分别分析

    源:InputStream Reader

    是不是纯文本?是!Reader

    设备:键盘。对应的对象是System.in。

    不是选择Reader吗?System.in对应的不是字节流吗?为了操作键盘的文本数据方便,转成字符流,按照字符串操作是最方便的。所以既然明确了Reader,那么就将System.in转换成字符流Reader。用到了Reader体系中的转换流,InputStreamReader

InputStreamReader isr = new InputStreamReader(System.in);

    需要提高效率吗?需要!BufferedReader 

BufferedReader bufr = new BufferedReader(isr);

    目的:OutputStream Writer

    是不是纯文本?是!Writer

    设备:硬盘上的一个文件。使用FileWriter。

FileWriter fw = new FileWriter("c.txt");

    需要提高效率吗?需要!BufferedWriter

BufferedWriter bufw = new BufferedWriter(fw);

  扩展一下,想要把录入的数据按照指定的编码表(UTF-8),将数据存到文件中,怎么办呢?

  分析:

    目的:OutputStream Writer

    是不是纯文本?是!Writer

    设备:硬盘上的一个文件。使用FileWriter。但是FileWriter是使用的默认编码表(GBK)

    但是存储时,需要加入指定的编码表(UTF-8),而指定的编码表只有转换流可以指定,所以要使用的对象是OutputStreamWriter。而该转换流对象要接收一个字节输出流,而且还可以操作文件的字节输出流,FileOutputStream。

OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("d.txt"), "UTF-8");

    需要提高效率吗?需要!BufferedWriter

BufferedWriter bufw = new BufferedWriter(osw);

  所以,记住,转换流什么时候使用?字符和字节之间的桥梁,通常涉及到字符编码转换时,需要用到转换流

练习:将一个文本数据打印在控制台上。

代码:

/** 练习:将一个文本数据打印在控制台上。*/
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.IOException;
import java.io.OutputStreamWriter;public class test1 {public static void main(String[] args) {BufferedReader br = null;BufferedWriter bw = null;String line = null;try {br = new BufferedReader(new FileReader("d:\\java\\ArrayTool.java"));bw = new BufferedWriter(new OutputStreamWriter(System.out));while((line = br.readLine()) != null) {bw.write(line);bw.newLine();bw.flush();}} catch (IOException e) {throw new RuntimeException("读取文件失败");} finally {try {if(br != null) br.close();} catch (IOException e) {throw new RuntimeException("读取流关闭失败");}try {if(bw != null)bw.close();} catch (IOException e) {throw new RuntimeException("写入流关闭失败");}}}}

异常的日志信息

 log4j:记录日志信息的一个工具。

示例代码如下:

import java.io.FileNotFoundException;
import java.io.PrintStream;
import java.text.SimpleDateFormat;
import java.util.Date;public class ExceptionInfo {public static void main(String[] args) {try {int[] arr = new int[2];System.out.println(arr[3]);} catch (Exception e) {try {Date d = new Date();SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");String s = sdf.format(d);PrintStream ps = new PrintStream("exception.log");//ps.write(d.toString().getBytes());
                ps.println(s);System.setOut(ps);} catch (FileNotFoundException e1) {throw new RuntimeException("日志文件创建失败!");}e.printStackTrace(System.out);//e.printStackTrace(new PrintStream("ex.txt"));
        }}}

系统信息

示例代码如下:

import java.io.FileNotFoundException;
import java.io.PrintStream;
import java.util.Properties;public class SystemInfo {public static void main(String[] args) throws FileNotFoundException {Properties pro = System.getProperties();//System.out.println(pro);pro.list(new PrintStream("sysinfo.txt"));}}

通过sysinfo.txt文本文件可以知道平台默认的字符集,即默认字符编码是GBK

转载于:https://www.cnblogs.com/yerenyuan/p/5269424.html

Java IO(二)相关推荐

  1. Java IO (二),常见的输入/输出流

    字节流和字符流 InputStream和Reader InputStream和Reader两个抽象类是所有输入流的基类,本身并不能创建实例来执行输入,但它们将成为所有输入流的模板.他们的方法是所有输入 ...

  2. Idea 导包自动变成星号 Idea 导包自动变成*号的问题 java.io.* Idea 自动导包变成星号

    Idea 导包自动变成星号 Idea 导包自动变成*号的问题 java.io.* Idea 自动导包变成星号 一.问题描述 1.在使用idea开发时,经常会出现导入的包自动变成 xx.*的情况,比如下 ...

  3. Java基础(二十七)Java IO(4)字符流(Character Stream)

    字符流用于处理字符数据的读取和写入,它以字符为单位. 一.Reader类与Writer类 1.Reader类是所有字符输入流的父类,它定义了操作字符输入流的各种方法. 2.Writer类是所有字符输出 ...

  4. Java IO流学习总结二:File

    转载请标明出处:http://blog.csdn.net/zhaoyanjun6/article/details/54581478 本文出自[赵彦军的博客] Java IO流学习总结一:输入输出流 J ...

  5. Java IO(input output)流二

    一.字符流的缓冲区 1.什么是缓冲区        缓冲区又称为缓存,它是内存空间的一部分.也就是说,在内存空间中预留了一定的存储空间,这些存储空间用来缓冲输入或输出的数据, 这部分预留的空间就叫做缓 ...

  6. java.io.FileNotFoundException异常,一是“拒绝访问”,二是“系统找不到指定路径”

    java.io.FileNotFoundException异常,一是"拒绝访问",二是"系统找不到指定路径" 参考文章: (1)java.io.FileNotF ...

  7. Java生成二维码并以IO流的形式返回给前端展示(不需写入服务器),以及下载二维码图片

    目录 场景 方案分析 第一步--引入依赖 第二步--编写工具类 第三步--编写API接口 第四步--访问测试 第五步--下载图片 场景 最近笔者做的项目中,有一个需求: 在系统中生成一个二维码,用户保 ...

  8. (十二)Core Java IO流(Properties,序列化,管道流,字符编码)-03 (108)

     目录 :             41 ). IO流(创建java文件列表) 42 ). IO流(Properties简述) 43 ). IO流(Properties存取) 44 ). IO流(Pr ...

  9. Java IO流 序列二:File类

    2019独角兽企业重金招聘Python工程师标准>>> 2.File API 2.1. File类简介 包路径:java.io.File 功能:用于表示文件或者目录. 说明:File ...

最新文章

  1. 离开页面前显示确认提示对话框(兼容IE,firefox) = how to Catch Win...
  2. 【AutoML】强化学习如何用于模型量化?
  3. mysql复制的工作原理及主从复制的实现
  4. 如何使用log.debug()
  5. 直面PHP微服务架构挑战
  6. 【数据结构与算法】布谷鸟散列表的Java实现
  7. 用 Java 拿下 HTML,分分钟写个小爬虫!
  8. (转载)C# Process.Kill() 拒绝访问(Access Denied) 的解决方案
  9. 大数据架构师必读的NoSQL建模技术
  10. CA证书服务器(6) 利用CA证书配置安全Web站点
  11. Java 调用gc语句_java GC机制(转)
  12. 微软输入法繁体简体切换
  13. 网恋背后的骗局:那些被宰杀掉的猪!必看!
  14. 黑客的专用通道以及入侵方法
  15. 学会这5个拍摄技巧,能让你的视频更好看
  16. ffmpeg中vf与filter_complex的区别
  17. 史上最全软件测试工程师常见的面试题总结(九)【多测师】
  18. tensorflow 之tf.Session
  19. javascript运算符_双重否定运算符是什么! 用JavaScript做?
  20. STC15单片机读写大容量SD卡(IO口模拟SPI模式)

热门文章

  1. 网盘(结合百度网盘/阿里网盘)
  2. 如何让谷歌、百度和雅虎收录你的网站,编入索引
  3. 电脑tf卡检测不到_内存卡在电脑上读不出来怎么办 内存卡在电脑上读不出来解决方法【详细介绍】...
  4. 2022-7-20 学习日记(11th day)String
  5. 通告功能、公告、消息(站内短信)、通告 (建表思路与功用)
  6. pwn,获取系统权限,入门题,cyclic
  7. nodejs 使用npm install express报错解决方案
  8. 淘宝商城开放的B2C平台战略
  9. 内连接和外连接 驱动表
  10. matlab 替代品_MATLAB的4种开源替代品