搜尋
首頁Javajava教程java i/o輸入輸出流的詳細介紹

java i/o輸入輸出流的詳細介紹

Jul 20, 2017 pm 02:23 PM
java輸入輸出

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

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)序列化中 子类和父类构造函数的调用问题

一个类实现了序列化接口,那么其子类都可以进行序列化

对子类对象进行反序列化操作时,如果其父类没有实现序列化接口那么其父类的构造函数就会被调用,否则就不会被调用。

以上是java i/o輸入輸出流的詳細介紹的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
如何將Maven或Gradle用於高級Java項目管理,構建自動化和依賴性解決方案?如何將Maven或Gradle用於高級Java項目管理,構建自動化和依賴性解決方案?Mar 17, 2025 pm 05:46 PM

本文討論了使用Maven和Gradle進行Java項目管理,構建自動化和依賴性解決方案,以比較其方法和優化策略。

如何使用適當的版本控制和依賴項管理創建和使用自定義Java庫(JAR文件)?如何使用適當的版本控制和依賴項管理創建和使用自定義Java庫(JAR文件)?Mar 17, 2025 pm 05:45 PM

本文使用Maven和Gradle之類的工具討論了具有適當的版本控制和依賴關係管理的自定義Java庫(JAR文件)的創建和使用。

如何使用咖啡因或Guava Cache等庫在Java應用程序中實現多層緩存?如何使用咖啡因或Guava Cache等庫在Java應用程序中實現多層緩存?Mar 17, 2025 pm 05:44 PM

本文討論了使用咖啡因和Guava緩存在Java中實施多層緩存以提高應用程序性能。它涵蓋設置,集成和績效優勢,以及配置和驅逐政策管理最佳PRA

如何將JPA(Java持久性API)用於具有高級功能(例如緩存和懶惰加載)的對象相關映射?如何將JPA(Java持久性API)用於具有高級功能(例如緩存和懶惰加載)的對象相關映射?Mar 17, 2025 pm 05:43 PM

本文討論了使用JPA進行對象相關映射,並具有高級功能,例如緩存和懶惰加載。它涵蓋了設置,實體映射和優化性能的最佳實踐,同時突出潛在的陷阱。[159個字符]

Java的類負載機制如何起作用,包括不同的類載荷及其委託模型?Java的類負載機制如何起作用,包括不同的類載荷及其委託模型?Mar 17, 2025 pm 05:35 PM

Java的類上載涉及使用帶有引導,擴展程序和應用程序類負載器的分層系統加載,鏈接和初始化類。父代授權模型確保首先加載核心類別,從而影響自定義類LOA

如何將Java的RMI(遠程方法調用)用於分佈式計算?如何將Java的RMI(遠程方法調用)用於分佈式計算?Mar 11, 2025 pm 05:53 PM

本文解釋了用於構建分佈式應用程序的Java的遠程方法調用(RMI)。 它詳細介紹了接口定義,實現,註冊表設置和客戶端調用,以解決網絡問題和安全性等挑戰。

如何使用Java的插座API進行網絡通信?如何使用Java的插座API進行網絡通信?Mar 11, 2025 pm 05:53 PM

本文詳細介紹了用於網絡通信的Java的套接字API,涵蓋了客戶服務器設置,數據處理和關鍵考慮因素,例如資源管理,錯誤處理和安全性。 它還探索了性能優化技術,我

如何在Java中創建自定義網絡協議?如何在Java中創建自定義網絡協議?Mar 11, 2025 pm 05:52 PM

本文詳細介紹了創建自定義Java網絡協議。 它涵蓋協議定義(數據結構,框架,錯誤處理,版本控制),實現(使用插座),數據序列化和最佳實踐(效率,安全性,維護

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
3 週前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳圖形設置
3 週前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您聽不到任何人,如何修復音頻
3 週前By尊渡假赌尊渡假赌尊渡假赌
WWE 2K25:如何解鎖Myrise中的所有內容
3 週前By尊渡假赌尊渡假赌尊渡假赌

熱工具

Atom編輯器mac版下載

Atom編輯器mac版下載

最受歡迎的的開源編輯器

mPDF

mPDF

mPDF是一個PHP庫,可以從UTF-8編碼的HTML產生PDF檔案。原作者Ian Back編寫mPDF以從他的網站上「即時」輸出PDF文件,並處理不同的語言。與原始腳本如HTML2FPDF相比,它的速度較慢,並且在使用Unicode字體時產生的檔案較大,但支援CSS樣式等,並進行了大量增強。支援幾乎所有語言,包括RTL(阿拉伯語和希伯來語)和CJK(中日韓)。支援嵌套的區塊級元素(如P、DIV),

MantisBT

MantisBT

Mantis是一個易於部署的基於Web的缺陷追蹤工具,用於幫助產品缺陷追蹤。它需要PHP、MySQL和一個Web伺服器。請查看我們的演示和託管服務。

Dreamweaver Mac版

Dreamweaver Mac版

視覺化網頁開發工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器