java.io 包几乎包含了所有操作输入、输出需要的类。所有这些流类代表了输入源和输出目标。java.io 包中的流支持很多种格式,比如:基本类型、对象、本地化字符集等等。一个流可以理解为一个数据的序列。输入流表示从一个源读取数据,输出流表示向一个目标写数据。Java 为 I/O 提供了强大的而灵活的支持,使其更广泛地应用到文件传输和网络编程中。 Java 的 I/O 大概可以分成以下几类: Java中IO操作有相应步骤,以文件操作为例,主要操作流程如下: 那么我们先来介绍一下File类 通过给定的父抽象路径名和子路径名字符串创建一个新的File实例。 通过将给定路径名字符串转换成抽象路径名来创建一个新 File 实例。 根据 parent 路径名字符串和 child 路径名字符串创建一个新 File 实例。 通过将给定的 file: URI 转换成一个抽象路径名来创建一个新的 File 实例。 注意: 创建File对象成功后,可以使用以下列表中的方法操作文件。 File1.png File2.png File3.png File4.png 下面给出一个使用File类的实例: 小贴士:lastModified()方法返回的是从时间戳(1970年1月1日0时0分0秒)到当前的毫秒数,返回值类型是long,可以用Date类对它进行包装使其更易读。 创建目录: mkdirs是递归创建文件夹,允许在创建某文件夹时其父文件夹不存在,从而一同创建;mkdir必须满足路径上的父文件夹全都存在 删除目录或文件: deleteFolder是一个递归函数,类似于DFS思想 RandomAccessFile不同于File,它提供了对文件内容的访问,可以读写文件且支持随机访问文件的任意位置。 RandomAccessFile.png public int read(int x) throws IOException 方法只读取一个字节,也就是x的低八位。 写完之后,开始读取数据。写的时候可以将一个字符串写入,读的时候需要一个个的以字节的形式读取出来。 结果如下: result.png 在Java程序中所有的数据都是以流的方式进行传输或保存的,程序需要数据的时候要使用输入流读取数据,而当程序需要将一些数据保存起来的时候,就要使用输出流完成。程序中的输入输出都是以流的形式保存的,流中保存的实际上全都是字节文件。流涉及的领域很广:标准输入输出,文件的操作,网络上的数据流,字符串流,对象流,zip文件流等等。 Stream.png 流具有方向性,至于是输入流还是输出流则是一个相对的概念,一般以程序为参考,如果数据的流向是程序至设备,我们成为输出流,反之我们称为输入流。 Information.jpg 先上一个Java IO流类层次图,如前所述,一个流被定义为一个数据序列。输入流用于从源读取数据,输出流用于向目标写数据: JavaIO流类层次图.png 是不是被吓到了?没关系,我们将通过一个个例子来学习这些功能。 1.按操作数据类型分:字符流和字节流 编码与解码:编码就是把字符转换为字节,而解码是把字节重新组合成字符。 UTF-16be 中的 be 指的是 Big Endian,也就是大端。相应地也有 UTF-16le,le 指的是 Little Endian,也就是小端。 字符流:Java中的字符流处理的最基本的单元是2字节的Unicode码元(char),它通常用来处理文本数据,如字符、字符数组或字符串等。所谓Unicode码元,也就是一个Unicode代码单元,范围是0x0000~0xFFFF。在以上范围内的每个数字都与一个字符相对应,Java中的String类型默认就把字符以Unicode规则编码而后存储在内存中。然而与存储在内存中不同,存储在磁盘上的数据通常有着各种各样的编码方式。使用不同的编码方式,相同的字符会有不同的二进制表示。实际上字符流是这样工作的: 也就是说,所有的文件在硬盘或在传输时都是以字节的方式进行的,包括图片等都是按字节的方式存储的,而字符是只有在内存中才会形成。 字节流:Java中的字节流处理的最基本单位为单个字节(byte),它通常用来处理二进制数据,如果要得到字节对应的字符需要强制类型转换。 两者比较: Compare.jpg 以向一个文件输出”Hello world!”为例,我们分别使用字节流和字符流进行输出,且在使用完之后都不关闭流。 使用字节流不关闭执行: 1.png 此时没有关闭字节流操作,但是文件中也依然存在了输出的内容,证明字节流是直接操作文件本身的。 使用字符流不关闭执行: 2.png 程序运行后会发现文件中没有任何内容,这是因为字符流操作时使用了缓冲区,而在关闭字符流时会强制性地将缓冲区中的内容进行输出,但是如果程序没有关闭字符流,缓冲区中的内容是无法输出的,所以得出结论:字符流使用了缓冲区,而字节流没有使用缓冲区。如果想让缓冲区中的内容输出,要么关闭流强制刷新缓冲区,要么调用flush方法冲刷缓冲区。可以简单地把缓冲区理解为一段特殊的内存。某些情况下,如果一个程序频繁地操作一个资源(如文件或数据库),则性能会很低,此时为了提升性能,就可以将一部分数据暂时读入到内存的一块区域之中,以后直接从此区域中读取数据即可,因为读取内存速度会比较快,这样可以提升程序的性能。 建议: 2.按流向分:输入流和输出流 输入流:程序从输入流读取数据源。数据源包括外界(键盘、文件、网络等),即是将数据源读入到程序的通信通道。输入流主要包括两个抽象基类:InputStream(字节输入流)和Reader(字符输入流)及其扩展的具体子类。 3.按功能分:节点流和处理流 按照流是否直接与特定的地方(如磁盘、内存、设备等)相连,分为节点流和处理流两类。 注意:在使用到处理流对流进行连接和封装时,读写完毕只需关闭处理流,不用关闭节点流。处理流关闭的时候,会调用其处理的节点流的关闭方法。如果将节点流关闭以后再关闭处理流,会抛出IO异常。 (1) 节点流 节点流.png 节点流示意图.png (1) 处理流 处理流.png 处理流示意图.png 在Java中,从控制台输入有三种方法: 1.使用标准输入流对象System.in System.in是System中内置的InputStream类对象,它的read方法一次只读入一个字节数据,返回0 ~ 255的一个byte值,一般用来读取一个字符,需要强制类型转换为char类型,而我们通常要取得一个字符串或一组数字,故这种方法不常用。下面给出这种方法的一个例子: 使用这种方法必须提供try-catch块或者在main方法首部声明IOException异常,因为System.in是一个流对象 2.使用Scanner类 Scanner类功能十分强大,可以读入字符串、整数、浮点数、布尔类型值等等。下面是例子: 注意: nextLine() 3.可以用循环配合hasNextXXX方法判断输入是否继续 更多Scanner的用法之前已经在Java学习总结之Java基本程序设计结构中总结过了,不再赘述。 3.使用BufferedReader对象 可以把 System.in 包装在一个 BufferedReader 对象中来创建一个字符流。 其中,System.in是一个InputStream对象(字节流),使用InputStreamReader作为桥梁,将字节流转换为字符流,然后再使用BufferedReader进行进一步包装。 下面的程序示范了用 read() 方法从控制台不断读取字符直到用户输入 “q”。 下面的程序读取和显示字符行直到你输入了单词”end”。 在ACM等算法竞赛中,我们常常也会使用Java,在输入数据时有以下几点注意: 控制台的输出由 print() 和 println() 完成。这些方法都由类 PrintStream 定义,System.out 是该类的一个对象。 注意:write() 方法不经常使用,因为 print() 和 println() 方法用起来更为方便。 字节流主要是操作byte类型的数据,以byte数组为准,主要操作类是OutputStream、InputStream。 FileInputStream 也可以使用一个文件对象来创建一个输入流对象来读取文件。我们首先得使用 File() 方法来创建一个文件对象: 创建了InputStream对象,就可以使用下面的方法来读取流或者进行其他的流操作。 InputStream.png 下面是一个例子: 当我们需要创建一个byte[]来保存读取的字节时,如果数组太小,无法完整读入数据,如果太大又会造成内存浪费。可以使用File类的length方法得到文件的数据字节数,从而有效确定byte数组的大小。 注意: 每调用一次read方法,当前读取在文件中的位置就会向后移动一个字节或者移动byte[]的长度(read的两个重载方法),已经到文件末尾会返回-1,可以通过read方法返回-1判断是否读到文件末尾,也可以使用available方法返回下一次可以不受阻塞读取的字节数来读取。FileInputStream不支持mark和reset方法进行重复读取。BufferedInputStream支持此操作。 FileOutputStream 也可以使用一个文件对象来创建一个输出流来写文件。我们首先得使用File()方法来创建一个文件对象: 之前的所有操作中,如果重新执行程序,则肯定会覆盖文件中的已有内容,那么此时就可以通过FileOutputStream向文件中追加内容,FileOutputStream的另外一个构造方法: 在构造方法中,如果将append的值设置为true,则表示在文件的末尾追加内容。程序代码如下: 创建OutputStream 对象完成后,就可以使用下面的方法来写入流或者进行其他的流操作。 FileOutputStream.png 当有一个字符串时,可以用getBytes方法转为byte数组用于字节流的输出。 下面是一个演示 InputStream 和 OutputStream 用法的例子: 上面的程序首先创建文件test.txt,并把给定的数字以二进制形式写进该文件,同时输出到控制台上。 以上例子证明:在对多国语言的支持上,字符流表现更优,此时应使用字符流而不是字节流。 还可以用InputStream和OutputStream配合进行文件的复制,即读取原件数据,写入副本文件。 在实际开发中建议使用边读边写的方式,代码如下: 实际上边读边写也分为三种方式: 第三种方式是最快的。 注意:InputStream的int read()方法读取一个字节,并用这个字节填充整型的低八位并返回,OutputStream的void write(int x)写入x的低八位,如果要写入一个int,需要移位并写4次。读写基本数据类型建议使用DataInputStream和DataOutputStream。小编推荐一个学Java的学习社区【 戳我立即加入 】,无论你是大牛还是小白,是想转行还是想入行都可以来了解一起进步一起学习!裙内有开发工具,很多干货和技术资料!概述
File
1.使用File类打开一个文件
2.通过字节流或字符流的子类,指定输出的位置
3.进行读/写操作
4.关闭输入/输出
Java文件类在java.io包中,它以抽象的方式代表文件名和目录路径名。该类主要用于获取文件和目录的属性,文件和目录的创建、查找、删除、重命名等,但不能进行文件的读写操作。
File对象代表磁盘中实际存在的文件和目录。通过以下构造方法创建一个File对象。File(File parent, String child)
File(String pathname)
File(String parent, String child)
File(URI uri)
1.在各个操作系统中,路径的分隔符是不一样的,例如:Windows中使用反斜杠:”“,Linux|Unix中使用正斜杠:”
/
“。在使用反斜杠时要写成”\
“的形式,因为反斜杠要进行转义。如果要让Java保持可移植性,应该使用File类的静态常量File.pathSeparator。
2.构建一个File实例并不会在机器上创建一个文件。不管文件是否存在,都可以创建任意文件名的File实例。可以调用File实例上的exists()方法来判断这个文件是否存在。通过后续的学习我们会知道,当把一个输出流绑定到一个不存在的File实例上时,会自动在机器上创建该文件,如果文件已经存在,把输出流绑定到该文件上则会覆盖该文件,但这些都不是在创建File实例时进行的。
import java.io.File; public class DirList { public static void main(String args[]) { String dirname = "/java"; File f1 = new File(dirname); if (f1.isDirectory()) { System.out.println( "Directory of " + dirname); String s[] = f1.list(); for (int i=0; i < s.length; i++) { File f = new File(dirname + "/" + s[i]); if (f.isDirectory()) { System.out.println(s[i] + " is a directory"); } else { System.out.println(s[i] + " is a file"); } } } else { System.out.println(dirname + " is not a directory"); } } }
Java中的目录
File类中有两个方法可以用来创建文件夹:
下面的例子创建 “/tmp/user/java/bin”文件夹:
import java.io.File; public class CreateDir { public static void main(String args[]) { String dirname = "/tmp/user/java/bin"; File d = new File(dirname); // 现在创建目录 d.mkdirs(); } }
注意: Java 在 UNIX 和 Windows 自动按约定分辨文件路径分隔符。如果你在 Windows 版本的 Java 中使用分隔符 (/) ,路径依然能够被正确解析。
读取目录:
一个目录其实就是一个 File 对象,它包含其他文件和文件夹。
如果创建一个 File 对象并且它是一个目录,那么调用 isDirectory() 方法会返回 true。
可以通过调用该对象上的 list() 方法,来提取它包含的文件和文件夹的列表。
下面展示的例子说明如何使用 list() 方法来检查一个文件夹中包含的内容:
import java.io.File; public class DirList { public static void main(String args[]) { String dirname = "/tmp"; File f1 = new File(dirname); if (f1.isDirectory()) { System.out.println( "目录 " + dirname); String s[] = f1.list(); for (int i=0; i < s.length; i++) { File f = new File(dirname + "/" + s[i]); if (f.isDirectory()) { System.out.println(s[i] + " 是一个目录"); } else { System.out.println(s[i] + " 是一个文件"); } } } else { System.out.println(dirname + " 不是一个目录"); } } }
删除文件可以使用 java.io.File.delete() 方法。
以下代码会删除目录/tmp/java/,即便目录不为空。
测试目录结构:
/tmp/java/ |-- 1.log |-- test
import java.io.File; public class DeleteFileDemo { public static void main(String args[]) { // 这里修改为自己的测试目录 File folder = new File("/tmp/java/"); deleteFolder(folder); } //删除文件及目录 public static void deleteFolder(File folder) { File[] files = folder.listFiles(); if(files!=null) { for(File f: files) { if(f.isDirectory()) { deleteFolder(f); } else { f.delete(); } } } folder.delete(); } }
RandomAccessFile
RandomAccessFile读写用到文件指针,它的初始位置为0,可以用getFilePointer()方法获取文件指针的位置。下面是RandomAccessFile常用的方法。
import java.io.File ; import java.io.RandomAccessFile ; public class RandomAccessFileDemo01{ // 所有的异常直接抛出,程序中不再进行处理 public static void main(String args[]) throws Exception{ File f = new File("d:" + File.separator + "test.txt") ; // 指定要操作的文件 RandomAccessFile rdf = null ; // 声明RandomAccessFile类的对象 rdf = new RandomAccessFile(f,"rw") ;// 读写模式,如果文件不存在,会自动创建 String name = null ; int age = 0 ; name = "zhangsan" ; // 字符串长度为8 age = 30 ; // 数字的长度为4 rdf.writeBytes(name) ; // 将姓名写入文件之中 rdf.writeInt(age) ; // 将年龄写入文件之中 name = "lisi " ; // 字符串长度为8 age = 31 ; // 数字的长度为4 rdf.writeBytes(name) ; // 将姓名写入文件之中 rdf.writeInt(age) ; // 将年龄写入文件之中 name = "wangwu " ; // 字符串长度为8 age = 32 ; // 数字的长度为4 rdf.writeBytes(name) ; // 将姓名写入文件之中 rdf.writeInt(age) ; // 将年龄写入文件之中 rdf.close() ; // 关闭 } };
import java.io.File ; import java.io.RandomAccessFile ; public class RandomAccessFileDemo02{ // 所有的异常直接抛出,程序中不再进行处理 public static void main(String args[]) throws Exception{ File f = new File("d:" + File.separator + "test.txt") ; // 指定要操作的文件 RandomAccessFile rdf = null ; // 声明RandomAccessFile类的对象 rdf = new RandomAccessFile(f,"r") ;// 以只读的方式打开文件 String name = null ; int age = 0 ; byte b[] = new byte[8] ; // 开辟byte数组 // 读取第二个人的信息,意味着要空出第一个人的信息 rdf.skipBytes(12) ; // 跳过第一个人的信息 for(int i=0;i<b.length;i++){ b[i] = rdf.readByte() ; // 读取一个字节 } name = new String(b) ; // 将读取出来的byte数组变为字符串 age = rdf.readInt() ; // 读取数字 System.out.println("第二个人的信息 --> 姓名:" + name + ";年龄:" + age) ; // 读取第一个人的信息 rdf.seek(0) ; // 指针回到文件的开头 for(int i=0;i<b.length;i++){ b[i] = rdf.readByte() ; // 读取一个字节 } name = new String(b) ; // 将读取出来的byte数组变为字符串 age = rdf.readInt() ; // 读取数字 System.out.println("第一个人的信息 --> 姓名:" + name + ";年龄:" + age) ; rdf.skipBytes(12) ; // 跳过第二个人的信息 for(int i=0;i<b.length;i++){ b[i] = rdf.readByte() ; // 读取一个字节 } name = new String(b) ; // 将读取出来的byte数组变为字符串 age = rdf.readInt() ; // 读取数字 System.out.println("第三个人的信息 --> 姓名:" + name + ";年龄:" + age) ; rdf.close() ; // 关闭 } };
流
可以将流想象成一个“水流管道”,水流就在这管道中形成了,自然就出现了方向的概念。IO流分类
如果编码和解码过程使用不同的编码方式那么就出现了乱码。
Java 使用双字节编码 UTF-16be,这不是指 Java 只支持这一种编码方式,而是说 char 这种类型使用 UTF-16be 进行编码。char 类型占 16 位,也就是两个字节,Java 使用这种双字节编码是为了让一个中文或者一个英文都能使用一个 char 来存储。
1.字符流是由Java虚拟机将字节转化为2个字节的Unicode字符为单位的字符而成的,所以它对多国语言支持性较好,如果要操作中文数据等,用字符流。
2.字符流只用来处理文本数据,字节流还可以用来处理媒体数据,如视频、音频、图片等。
3.字符流的两个抽象基类为Reader和Writer,字节流的两个抽象基类为InputStream和OutputStream。它们的具体子类名以基类名为后缀进行扩展。
4.字节流在操作的时候不会用到缓冲区(内存),是直接对文件本身操作的,而字符流在操作的时候使用缓冲区。
import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; public class IOPractice { public static void main(String[] args) throws IOException { // 第1步:使用File类找到一个文件 File f = new File("/home/xiejunyu/"+ "桌面/text.txt"); // 第2步:通过子类实例化父类对象 OutputStream out = new FileOutputStream(f); // 通过对象多态性进行实例化 // 第3步:进行写操作 String str = "Hello World!"; // 准备一个字符串 byte b[] = str.getBytes(); // 字符串转byte数组 out.write(b); // 将内容输出 // 第4步:关闭输出流 // out.close(); // 此时没有关闭 } }
import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.io.Writer; public class IOPractice { public static void main(String[] args) throws IOException { // 第1步:使用File类找到一个文件 File f = new File("/home/xiejunyu/桌面/test.txt"); // 第2步:通过子类实例化父类对象 Writer out = new FileWriter(f); // 第3步:进行写操作 String str = "Hello World!"; // 准备一个字符串 out.write(str); // 将内容输出 // 第4步:关闭输出流 // out.close(); // 此时没有关闭 } }
在字符流的操作中,所有的字符都是在内存中形成的,在输出前会将所有的内容暂时保存在内存之中,所以使用了缓冲区暂存数据。
1.虽然不关闭字节流不影响数据的输出,且后续JVM会自动回收这部分内存,但还是建议在使用完任何流对象之后关闭流。
2.使用流对象都要声明或抛出IOException
3.在创建一个文件时,如果目录下有同名文件将被覆盖
4.在写文件时,如果文件不存在,会在创建输出流对象并绑定文件时自动创建文件,不必使用File的exists方法提前检测
4.在读取文件时,必须使用File的exists方法提前检测来保证该文件已存在,否则抛出FileNotFoundException
输出流:程序向输出流写入数据。将程序中的数据输出到外界(显示器、打印机、文件、网络等)的通信通道。输出流主要包括两个抽象基类:OutputStream(字节输出流)和Writer(字符输出流)及其扩展的具体子类。
节点流:程序用于直接操作目标设备所对应的类叫节点流。(低级流)
处理流:程序通过一个间接流类去调用节点流类,以达到更加灵活方便地读写各种类型的数据,这个间接流类就是处理流。处理流可以看成是对已存在的流进行连接和封装的流。(高级流)
向内存数组读写数据: CharArrayReader与 CharArrayWriter、ByteArrayInputStream与ByteArrayOutputStream。
向内存字符串读写数据:StringReader、StringWriter、StringBufferInputStream。
读取控制台输入
public class CharTest{ public static void main(String[] args) { try{ System.out.print("Enter a Char:"); char i = (char)System.in.read(); System.out.println("Yout Enter Char is:" + i); } catch(IOException e){ e.printStackTrace(); } } }
public class ScannerTest{ public static void main(String[] args){ Scanner sc = new Scanner(System.in); System.out.println("ScannerTest, Please Enter Name:"); String name = sc.nextLine(); //读取字符串型输入 System.out.println("ScannerTest, Please Enter Age:"); int age = sc.nextInt(); //读取整型输入 System.out.println("ScannerTest, Please Enter Salary:"); float salary = sc.nextFloat(); //读取float型输入 System.out.println("Your Information is as below:"); System.out.println("Name:" + name +"n" + "Age:"+age + "n"+"Salary:"+salary); } }
1.用nextXXX()读入XXX类型的数据,XXX可以是除了char外的所有基本数据类型,还可以是BigInteger或BigDecimal,其中凡是整型类型的数据还可以指定radix(进制),可以用next()和nextLine()读取一个字符串或一行字符
2.next()和nextLine()的区别:
next()
4.Scanner类没有直接提供读取一个字符的方法,如果要读取一个字符,有三种方法,一是读入一个字符串后取字符串的第一个字符,二是使用System.in的read方法,三是使用字符流读入
下面是创建 BufferedReader 的基本语法:
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedReader 对象创建后,我们便可以使用 read() 方法从控制台读取一个字符(读入一个用0~65535之间的整数表示的字符,需要强制类型转换为char类型,如果已到达流末尾,则返回 -1),或者用 readLine() 方法读取一个字符串。下面是例子:
public static void main(String[] args){ //必须要处理java.io.IOException异常 BufferedReader br = new BufferedReader(new InputStreamReader (System.in )); //java.io.InputStreamReader继承了Reader类 String read = null; System.out.print("输入数据:"); try { read = br.readLine(); } catch (IOException e) { e.printStackTrace(); } System.out.println("输入数据:"+read); }
// 使用 BufferedReader 在控制台读取字符 import java.io.*; public class BRRead { public static void main(String args[]) throws IOException { char c; // 使用 System.in 创建 BufferedReader BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); System.out.println("输入字符, 按下 'q' 键退出。"); // 读取字符 do { c = (char) br.read(); System.out.println(c); } while(c != 'q'); } }
// 使用 BufferedReader 在控制台读取字符 import java.io.*; public class BRReadLines { public static void main(String args[]) throws IOException { // 使用 System.in 创建 BufferedReader BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); String str; System.out.println("Enter lines of text."); System.out.println("Enter 'end' to quit."); do { str = br.readLine(); System.out.println(str); } while(!str.equals("end")); } }
1.hasXXX等价于C++中读到文件末尾(EOF)
2.使用BufferedReader输入会比Scanner输入快十倍左右!控制台输出
PrintStream 继承了 OutputStream类,并且实现了方法 write()。这样,write() 也可以用来往控制台写操作。
PrintStream 定义 write() 的最简单格式如下所示:void write(int byteval)
该方法将 byteval 的低八位字节写到流中,即System.out的write方法一次只能写一个字节(类比System.in的read方法一次只能读取一个字节)。
下面的例子用 write() 把字符 “A” 和紧跟着的换行符输出到屏幕:
import java.io.*; // 演示 System.out.write(). public class WriteDemo { public static void main(String args[]) { int b; b = 'A';//向上类型转换 System.out.write(b); System.out.write('n'); } }
字节流(OutputStream、InputStream)
由于文件读写最为常见,我们先讨论两个重要的字节流 FileInputStream(文件输入流) 和 FileOutputStream(文件输出流),分别是抽象类InputStream和OutputStream的具体子类:
该流用于从文件读取数据,它的对象可以用关键字 new 来创建。
有多种构造方法可用来创建对象。
可以使用字符串类型的文件名来创建一个输入流对象来读取文件:
InputStream f = new FileInputStream("C:/java/hello");
File f = new File("C:/java/hello"); InputStream in = new FileInputStream(f);
public static void main(String[] args) throws IOException{ InputStream f = new FileInputStream ("/home/xiejunyu/桌面/test.txt"); int c = 0; while((c = f.read()) != -1) //这里也可以先用available方法得到可读的字节数 System.out.println((char)c); }
public static void main(String[] args) { // 创建一个FileInputStream对象 try { FileInputStream fis = new FileInputStream("/home/xiejunyu/桌面/test.txt"); byte[] b=new byte[100]; fis.read(b,0,5); /*把字节从文件读入b数组,从b数组的0位置开始存放, 读取5个字节*/ System.out.println(new String(b)); fis.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } }
该类用来创建一个文件并向文件中写数据。
如果该流在打开文件进行输出前,目标文件不存在,那么该流会创建该文件。
有两个构造方法可以用来创建 FileOutputStream 对象。
使用字符串类型的文件名来创建一个输出流对象:
OutputStream f = new FileOutputStream("C:/java/hello")
File f = new File("C:/java/hello"); OutputStream f = new FileOutputStream(f);
public FileOutputStream(File file,boolean append)
File f = new File("C:/java/hello"); OutputStream f = new FileOutputStream(f,true);
import java.io.*; public class FileStreamTest{ public static void main(String args[]){ try{ byte bWrite[] = "ABC".getBytes(); OutputStream os = new FileOutputStream("/home/xiejunyu/桌面/test.txt"); for(int x=0; x < bWrite.length ; x++){ os.write(bWrite[x] ); // writes the bytes } os.close(); InputStream is = new FileInputStream("/home/xiejunyu/桌面/test.txt"); int size = is.available(); for(int i=0; i< size; i++){ System.out.print((char)is.read() + " "); } is.close(); }catch(IOException e){ System.out.print("Exception"); } } }
以上代码由于是二进制写入,可能存在乱码,你可以使用以下代码实例来解决乱码问题:
import java.io.*; public class fileStreamTest2{ public static void main(String[] args) throws IOException { File f = new File("a.txt"); FileOutputStream fop = new FileOutputStream(f); // 构建FileOutputStream对象,文件不存在会自动新建;如果存在会覆盖原文件 OutputStreamWriter writer = new OutputStreamWriter(fop, "UTF-8"); // 构建OutputStreamWriter对象,参数可以指定编码,默认为操作系统默认编码,windows上是gbk writer.append("中文输入"); // 写入到缓冲区 writer.append("rn"); //换行 writer.append("English"); // 刷新缓冲区,写入到文件,如果下面已经没有写入的内容了,直接close也会写入 writer.close(); //关闭写入流,同时会把缓冲区内容写入文件,所以上面的注释掉 fop.close(); // 关闭输出流,释放系统资源 FileInputStream fip = new FileInputStream(f); // 构建FileInputStream对象 InputStreamReader reader = new InputStreamReader(fip, "UTF-8"); // 构建InputStreamReader对象,编码与写入相同 StringBuffer sb = new StringBuffer(); while (reader.ready()) { sb.append((char) reader.read()); // 转成char加到StringBuffer对象中 } System.out.println(sb.toString()); reader.close(); // 关闭读取流 fip.close(); // 关闭输入流,释放系统资源 } }
复制有两种实现方式:
实现一:将源文件中的内容全部读取进来,之后一次性的写入到目标文件
实现二:边读边写
public static void main(String[] args) { // 文件拷贝 try { FileInputStream fis=new FileInputStream("happy.gif"); FileOutputStream fos=new FileOutputStream("happycopy.gif"); int n=0; byte[] b=new byte[1024]; while((n=fis.read(b))!=-1){ /*循环读取,每次1024个字节,最后一次可能不满1024。 后面的字节覆盖前面的字节,不必担心数组溢出。*/ fos.write(b,0,n); //n是实际读取到的字节数,如果写fos.write(b),会造成最后一次数组未满的情况也写1024个字节,从而造成副本比原件略大 } fis.close(); fos.close(); } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); }catch(IOException e){ e.printStackTrace(); } }
1.批量拷贝(循环读取,每次读入一个byte数组)
2.缓冲拷贝(使用缓冲流)
3.批量+缓冲拷贝(循环批量读取到字节数组中,然后使用缓冲输出流写入到文件)
本网页所有视频内容由 imoviebox边看边下-网页视频下载, iurlBox网页地址收藏管理器 下载并得到。
ImovieBox网页视频下载器 下载地址: ImovieBox网页视频下载器-最新版本下载
本文章由: imapbox邮箱云存储,邮箱网盘,ImageBox 图片批量下载器,网页图片批量下载专家,网页图片批量下载器,获取到文章图片,imoviebox网页视频批量下载器,下载视频内容,为您提供.
阅读和此文章类似的: 全球云计算