Detailed introduction to java i/o input and output streams
Java流的分类
按流向分:
输入流: 程序可以从中读取数据的流。
输出流: 程序能向其中写入数据的流。
按数据传输单位分:
字节流: 以字节为单位传输数据的流
字符流: 以字符为单位传输数据的流
按功能分:
节点流: 用于直接操作目标设备的流
处理流: 是对一个已存在的流的链接和封装,通过对数据进行处理为程序提供功能强大、灵活的读写功能。
1、编码问题
String s = "哈喽ABC";byte[] bytes1 = s.getBytes();//转换成字节序列用的是项目默认的编码utf-8for (byte b : bytes1) {//把字节(转换成了int)以16进制的方式显示//把byte转换成int 其实就是把后8位前面添24个0变成32位变成4个字节//前24个0没有意义,所以位与上0xff是把前24个0去掉 只留下后8位System.out.print(Integer.toHexString(b&0xff)+" ");//输出e5 93 88 e5 96 bd 41 42 43 } System.out.println();byte[] bytes2 = s.getBytes("gbk");for (byte b : bytes2) { System.out.print(Integer.toHexString(b&0xff)+" ");//输出b9 fe e0 b6 41 42 43 }//结论:gbk编码中文占用2个字节,英文占用1个字节;utf-8编码中文占用3个字节,英文占用1个字节 System.out.println();//java是双字节编码 utf-16bebyte[] bytes3 = s.getBytes("utf-16be");for (byte b : bytes3) { System.out.print(Integer.toHexString(b&0xff)+" "); }//结论:utf-16be中文占用2个字节,英文占用2个字节 System.out.println();/* * 当你的字节序列是某种编码时,这个时候想把字节序列变成字符串, * 也需要用这种编码方式,否则会出现乱码 */String str1 = new String(bytes3); System.out.println(str1);//输出:T�U� A B CString str2 = new String(bytes3,"utf-16be"); System.out.println(str2);//输出:哈喽ABC/* * 文本文件 就是字节序列 * 可以是任意编码的字节序列 * 如果我们在中文机器上直接创建文本文件,那么该文本文件只认识ANSI编码 * 联通、联这是一种巧合,他们正好符合了utf-8编码的规则 */
2、File类的使用
java.io.File类用于表示文件(目录)
File类只用于表示文件(目录)的信息(名称、大小等),不能用于文件内容的访问
(1)File类的常用api
File file = new File("e:\\javaio"); File file2 = new File("e:"+File.separator+"javaio"); System.out.println(file.exists());if(!file.exists()) file.mkdir();elsefile.delete();//是否是一个目录 如果是目录返回true,如果不是目录or目录不存在返回的是false System.out.println(file.isDirectory());//是否是一个文件 System.out.println(file.isFile()); File file3 = new File("e:"+File.separator+"javaio"+File.separator+"test.txt");//File file3 = new File("e:\\javaid","test.txt");if(!file3.exists())try { file3.createNewFile(); } catch (IOException e) {// TODO Auto-generated catch block e.printStackTrace(); }elsefile3.delete(); System.out.println(file);//file.toString()的内容//e:\javaioSystem.out.println(file.getAbsolutePath());//e:\javaioSystem.out.println(file.getName());//javaioSystem.out.println(file3.getName());//test.txtSystem.out.println(file.getParent());//e:\System.out.println(file3.getParent());//e:\javaioSystem.out.println(file.getParentFile().getAbsolutePath());//e:\
(2)遍历目录
//列出File的一些常用的操作比如过滤、遍历等操作public class FileUtils {/** * 列出指定目录下(包括其子目录)的所有文件 */public static void listDirectory(File dir){if(!dir.exists()){throw new IllegalArgumentException("目录"+dir+"不存在"); }if(!dir.isDirectory()){throw new IllegalArgumentException(dir+"不是目录"); }//返回的是字符串数组 直接子的名称,不包含子目录下的内容String[] filenames = dir.list();for (String string : filenames) { System.out.println(dir+"\\"+string); }//如果要遍历子目录下的内容就需要构造成File对象做递归操作,File提供了直接返回File对象的APIFile[] files = dir.listFiles();//返回的是直接子目录(文件)的抽象for (File file : files) { System.out.println(file); }if(files!=null&&files.length>0)for (File file : files) {if(file.isDirectory()){//递归 listDirectory(file); }else{ System.out.println(file); } } } }
3、RandomAccessFile java提供的对文件内容的访问,既可以读文件,也可以写文件。
RandomAccessFile 支持随机访问文件,可以访问文件的任意位置
(1)java文件模型
在硬盘上的文件是byte byte byte存储的,是数据的集合
(2)打开文件
有两种模式“rw”(读写)“r”(只读)
RandomAccessFile raf = new RandomAccessFile (file,"rw");
文件指针,打开文件时指针在开头pointer=0;
(3)写方法
raf.write(int)--->只写一个字节(后8位),同事指针指向下一个位置,准备再次写入
(4)读方法
int b = raf.read()--->读一个字节
(5)文件读写完成以后一定要关闭。
File demo = new File("demo");if(!demo.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'); 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.write(i); String s1 = "中";byte[] gbk = s1.getBytes("gbk"); 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)); String s2 = new String(buf);for (byte b : buf) { System.out.print(Integer.toHexString(b&0xff)+" "); } raf.close();
4、IO流(输入流、输出流)
字节流、字符流
(1)字节流
1)InputStream、OutputStream
InputStream抽象了应用程序读取数据的方式
OutputStream抽象了应用程序写出数据的方式
2)EOF = End 读到-1就读到结尾
3)输入流基本方法
int b=in.read();读取一个字节无符号填充到int低8位。-1是EOF
in.read(byte[] buf) 读取数据填充到字节数组buf
in.read(byte[] buf,int start, int size)读取数据到字节数组buf,从buf的start位置开始存放size长度的数据
4)输出流基本方法
out.write(int b) 写出一个byte到流,b的低8位
out.write(byte[] buf) 将buf字节数组都写入到流
out.write(bytep[] buf, int start ,int size) 字节数组buf从start位置开始写size长度的字节到流
5)FileInputStream--->具体实现了在文件上读取数据
public class IOUtil {/** * 读取指定文件内容,按照16进制输出到控制台 * 并且每输出10个byte换行 * @param fileName */public static void printHex(String fileName)throws IOException{//把文件作为字节流进行操作FileInputStream in = new FileInputStream(fileName);int b;int i = 1;while((b=in.read())!=-1){if(b<=0xf){//单位数前面补0System.out.print("0"); } System.out.print(Integer.toHexString(b)+" ");//将整型b转换为16进制表示的字符串if(i++%10==0){ System.out.println(); } } in.close(); }public static void printHexByByteArray(String fileName)throws IOException{ FileInputStream in = new FileInputStream(fileName);byte[] buf = new byte[20*1024];/* * 从in中批量读取字节,放入到buf这个字节数组中, * 从第0个位置开始放,最多放buf.length个 * 返回的是读到的字节的个数 */int bytes = in.read(buf,0,buf.length);//一次性读完,说明字节数组足够大int j = 1;for (int i = 0; i < bytes; i++) {if(buf[i]<=0xf){ System.out.println("0"); } System.out.println(Integer.toHexString(buf[i]&0xff)+" ");if(j++%10==0){ System.out.println(); } } int bytes2 = 0;while((bytes2=in.read(buf,0,buf.length))!=-1){for (int i = 0; i < bytes2; i++) {// byte类型8位,int类型32位,// 为了避免数据转换错误,通过&0xff将高24位清0System.out.println(Integer.toHexString(buf[i]&0xff)+" ");if(j++%10==0){ System.out.println(); } } }
6)FileOutputStream 实现了向文件中写出byte数据的方法
/** * 文件拷贝 * @param srcFile * @param destFile * @throws IOException */public static void copyFile(File srcFile,File destFile)throws IOException{if(!srcFile.exists()){throw new IllegalArgumentException("文件"+srcFile+"不存在"); }if(!srcFile.isFile()){throw new IllegalAccessError(srcFile+"不是文件"); } FileInputStream in = new FileInputStream(srcFile); FileOutputStream out = new FileOutputStream(destFile);byte[] buf = new byte[8*1024];int b;while((b=in.read(buf,0,buf.length))!=-1){ out.write(buf,0,b); out.flush();//最好加上 } in.close(); out.close(); }
7)DataOutputStream和DataInputStream
对“流”功能的扩展,可以更加方便的读取int,long,字符等类型数据
DataOutputStream
writeInt()/writeDouble()/writeUTF()
String file = "dos.dat"; DataOutputStream dos = new DataOutputStream(new FileOutputStream(file)); dos.writeInt(20); dos.writeInt(-10); dos.writeLong(10l); dos.writeDouble(10.3);//采用utf-8编码写出dos.writeUTF("中国");//采用utf-16be编码写出dos.writeChars("中国"); dos.close(); IOUtil.printHex(file);
DataInputStream
String file2 = "dos.dat"; IOUtil.printHex(file2); DataInputStream dis = new DataInputStream(new FileInputStream(file2)); System.out.println();int i = dis.readInt(); System.out.println(i); i = dis.readInt(); System.out.println(i);long l = dis.readLong(); System.out.println(l);double d = dis.readDouble(); System.out.println(d); String s = dis.readUTF(); System.out.println(s); dis.close();
8)BufferedInputStream和BufferedOutputStream
这两个流类为IO提供了带缓冲区的操作,一般打开文件进行写入或读取操作时,都会加上缓冲,这种流模式提高了IO的性能
从应用程序中把输入放入文件,相当于将一缸水倒入到另一个缸中:
FileOutputStream--->write()方法相当于一滴一滴地把水“转移”过去
DataOutputStream--->writeXxx()方法相当于一瓢一瓢把水转移过去
BufferedOutputStream--->write()方法更方便,相当于一瓢一瓢先放入桶中,再从桶中倒入到另一个缸中
/** * 文件拷贝 * @param srcFile * @param destFile * @throws IOException */public static void copyFile(File srcFile,File destFile)throws IOException{if(!srcFile.exists()){throw new IllegalArgumentException("文件"+srcFile+"不存在"); }if(!srcFile.isFile()){throw new IllegalAccessError(srcFile+"不是文件"); } FileInputStream in = new FileInputStream(srcFile); FileOutputStream out = new FileOutputStream(destFile);byte[] buf = new byte[8*1024];int b;while((b=in.read(buf,0,buf.length))!=-1){ out.write(buf,0,b); out.flush();//最好加上 } in.close(); out.close(); } /** * 进行文件拷贝,利用DataInputStream和DataOutputStream * @param srcFile * @param destFile * @throws IOException */public static void copyFileByData(File srcFile,File destFile)throws IOException{if(!srcFile.exists()){throw new IllegalArgumentException("文件"+srcFile+"不存在"); }if(!srcFile.isFile()){throw new IllegalArgumentException(srcFile+"不是文件"); } DataInputStream bis = new DataInputStream(new FileInputStream(srcFile)); DataOutputStream bos = new DataOutputStream(new FileOutputStream(destFile));byte[] buf = new byte[8*1024];int c;while((c=bis.read(buf,0,buf.length))!=-1){ bos.write(buf,0,c); bos.flush(); } bis.close(); bos.close(); }/** * 进行文件拷贝,利用带缓冲的字节流 * @param srcFile * @param destFile * @throws IOException */public static void copyFileByBuffer(File srcFile,File destFile)throws IOException{if(!srcFile.exists()){throw new IllegalArgumentException("文件"+srcFile+"不存在"); }if(!srcFile.isFile()){throw new IllegalArgumentException(srcFile+"不是文件"); } BufferedInputStream bis = new BufferedInputStream(new FileInputStream(srcFile)); BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(destFile));byte[] buf = new byte[8*1024];int c;while((c=bis.read(buf,0,buf.length))!=-1){ bos.write(buf,0,c); bos.flush(); } bis.close(); bos.close(); }
(2)字符流
Reader Writer
字符的处理,一次处理一个字符
字符的底层仍然是基本的字节序列
字符流的基本实现
InputStreamReader 完成byte流解析为char流,按照编码解析
OutputStreamWriter 提供char流到byte流,按照编码处理
InputStreamReader isr = new InputStreamReader(new FileInputStream("out.dat"),"gbk");//默认项目的编码,操作的时候要写文件本身的编码FileOutputStream out = new FileOutputStream("out2.dat"); OutputStreamWriter osw = new OutputStreamWriter(out,"utf-8");// int c;// while((c=isr.read())!=-1){// System.out.print((char)c);// }char[] buffer = new char[8*1024];int c;//批量读取,放入buffer这个字符数组,从第0个位置开始放置,最多放buffer.length//返回的是读到的字符的个数while((c=isr.read(buffer, 0, buffer.length))!=-1){//需要把这个字符数组构造成字符串String s = new String(buffer,0,c); System.out.print(s); osw.write(buffer,0,c); osw.flush(); } isr.close(); osw.close();
FileReader、FileWriter
FileReader fr = new FileReader("out.dat"); FileWriter fw = new FileWriter("out3.dat");// FileWriter fw = new FileWriter("out3.dat");char[] buffer = new char[2056];int c;while((c=fr.read(buffer ,0,buffer.length))!=-1){ fw.write(buffer,0,c); fw.flush(); } fr.close(); fw.close();
字符流过滤器
BufferedReader --->readLine 一次读一行
BufferedWriter/PrinterWriter --->写一行
//对文件进行读写操作BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("out.dat"),"gbk")); BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("out4.dat"))); PrintWriter pw = new PrintWriter("out5.dat");//PrintWriter pw2 = new PrintWriter(outputStream,boolean autoFlush); String line;while((line=br.readLine())!=null){ System.out.println(line);//一次读一行,并不能识别换行 bw.write(line);//单独写出换行操作bw.newLine();//换行操作 bw.flush(); pw.println(line); pw.flush(); } br.close(); bw.close(); pw.close();
5、对象的序列化,反序列化
(1)对象的序列化,就是将Object转换成byte序列,反之叫对象的反序列化
(2)序列化流(ObjectOutputStream),是过滤流----writeObject
反序列化流(ObjectInputStream)----readObject
(3)序列化接口(Serializable)
对象必须实现序列化接口,才能进行序列化,否则将出现异常
这个接口,没有任何方法,只是一个标准
String file = "stu.dat";//1.对象的序列化ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(file)); Student stu = new Student("10001","张三",20); oos.writeObject(stu); oos.flush(); oos.close(); //2.对象的反序列化ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file)); Student stu1 = (Student)ois.readObject(); System.out.println(stu1); ois.close();
(4)transient关键字
private void writeObject(java.io.ObjectOutputStream s)throws java.io.IOException
private void readObject(java.io.ObjectInputStream s)
throws java.io.IOException, ClassNotFoundException
分析ArrayList源码中序列化和反序列化的问题
public class Student implements Serializable{private String stuno;private String stuname;private transient int stuage;//加了transient关键字,则该元素不会进行jvm默认的序列化,也可以自己完成这个元素的序列化public Student(){} public Student(String stuno, String stuname, int stuage) {super();this.stuno = stuno;this.stuname = stuname;this.stuage = stuage; }public String getStuno() {return stuno; }public void setStuno(String stuno) {this.stuno = stuno; }public String getStuname() {return stuname; }public void setStuname(String stuname) {this.stuname = stuname; }public int getStuage() {return stuage; }public void setStuage(int stuage) {this.stuage = stuage; } @Overridepublic String toString() {return "Student [stuno=" + stuno + ", stuname=" + stuname + ", stuage=" + stuage + "]"; }private void writeObject(java.io.ObjectOutputStream s)throws java.io.IOException{ s.defaultWriteObject();//把jvm能默认序列化的元素进行序列化操作s.writeInt(stuage);//自己完成student的序列化(stuage用transient修饰了,也可以自己序列化) }private void readObject(java.io.ObjectInputStream s)throws java.io.IOException, ClassNotFoundException{ s.defaultReadObject();//把jvm能默认反序列化的元素进行反序列化操作this.stuage = s.readInt();//自己完成stuage的反序列化操作 } }
(5)序列化中 子类和父类构造函数的调用问题
一个类实现了序列化接口,那么其子类都可以进行序列化
对子类对象进行反序列化操作时,如果其父类没有实现序列化接口那么其父类的构造函数就会被调用,否则就不会被调用。
The above is the detailed content of Detailed introduction to java i/o input and output streams. For more information, please follow other related articles on the PHP Chinese website!

Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

Video Face Swap
Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Hot Tools

Notepad++7.3.1
Easy-to-use and free code editor

SublimeText3 Chinese version
Chinese version, very easy to use

Zend Studio 13.0.1
Powerful PHP integrated development environment

Dreamweaver CS6
Visual web development tools

SublimeText3 Mac version
God-level code editing software (SublimeText3)

Hot Topics

Guide to Smith Number in Java. Here we discuss the Definition, How to check smith number in Java? example with code implementation.

In this article, we have kept the most asked Java Spring Interview Questions with their detailed answers. So that you can crack the interview.

Java 8 introduces the Stream API, providing a powerful and expressive way to process data collections. However, a common question when using Stream is: How to break or return from a forEach operation? Traditional loops allow for early interruption or return, but Stream's forEach method does not directly support this method. This article will explain the reasons and explore alternative methods for implementing premature termination in Stream processing systems. Further reading: Java Stream API improvements Understand Stream forEach The forEach method is a terminal operation that performs one operation on each element in the Stream. Its design intention is

Guide to TimeStamp to Date in Java. Here we also discuss the introduction and how to convert timestamp to date in java along with examples.

Capsules are three-dimensional geometric figures, composed of a cylinder and a hemisphere at both ends. The volume of the capsule can be calculated by adding the volume of the cylinder and the volume of the hemisphere at both ends. This tutorial will discuss how to calculate the volume of a given capsule in Java using different methods. Capsule volume formula The formula for capsule volume is as follows: Capsule volume = Cylindrical volume Volume Two hemisphere volume in, r: The radius of the hemisphere. h: The height of the cylinder (excluding the hemisphere). Example 1 enter Radius = 5 units Height = 10 units Output Volume = 1570.8 cubic units explain Calculate volume using formula: Volume = π × r2 × h (4

PHP and Python each have their own advantages, and the choice should be based on project requirements. 1.PHP is suitable for web development, with simple syntax and high execution efficiency. 2. Python is suitable for data science and machine learning, with concise syntax and rich libraries.

PHP is a scripting language widely used on the server side, especially suitable for web development. 1.PHP can embed HTML, process HTTP requests and responses, and supports a variety of databases. 2.PHP is used to generate dynamic web content, process form data, access databases, etc., with strong community support and open source resources. 3. PHP is an interpreted language, and the execution process includes lexical analysis, grammatical analysis, compilation and execution. 4.PHP can be combined with MySQL for advanced applications such as user registration systems. 5. When debugging PHP, you can use functions such as error_reporting() and var_dump(). 6. Optimize PHP code to use caching mechanisms, optimize database queries and use built-in functions. 7

Java is a popular programming language that can be learned by both beginners and experienced developers. This tutorial starts with basic concepts and progresses through advanced topics. After installing the Java Development Kit, you can practice programming by creating a simple "Hello, World!" program. After you understand the code, use the command prompt to compile and run the program, and "Hello, World!" will be output on the console. Learning Java starts your programming journey, and as your mastery deepens, you can create more complex applications.
