Java 流(Stream)、文件(File)和IO
Java.io 包几乎包含了所有操作输入、输出需要的类。所有这些流类代表了输入源和输出目标。
Java.io包中的流支持很多种格式,比如:基本类型、对象、本地化字符等等。
一个流可以理解为一个数据序列。输入流表示从一个源读取数据,输出流表示向一个目标写数据。
Java为I/O提供了强大而灵活的支持,使其更广泛地应用到文件传输和网络编程中。
读取控制台输入
Java 的控制台输入由 System.in 完成。
为了获得一个绑定到控制台的字符流,你可以把 System.in 包装在一个 BufferedReader 对象中来创建一个字符流。
下面是创建 BufferedReader 的基本语法:
BufferedReader br = new BufferedReader(new
InputStreamReader(System.in));
从控制台读取多字符输入
每次调用 read() 方法,它从输入流读取一个字符并把该字符作为整数值返回。 当流结束的时候返回 -1。该方法抛出 IOException。
eg.
// 使用 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');
}
}
结果为:
输入字符, 按下 'q' 键退出。
ki gang
k
i
g
a
n
g
q
q
从控制台读取字符串
- 从标准输入读取一个字符串需要使用 BufferedReader 的 readLine() 方法。
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("输入字符串.");
System.out.println("请以 end 结束.");
do {
str = br.readLine();
System.out.println(str);
} while(!str.equals("end"));
}
}
结果为:
输入字符串.
请以 end 结束.
ki gang end
ki gang end
JDK 5 后,用Scanner类来获取控制台的输入
通过 Scanner 类的 next() 与 nextLine() 方法获取输入的字符串,在读取前我们一般需要 使用 hasNext 与 hasNextLine 判断是否还有输入的数据:
eg.
import java.util.Scanner;
public class ScannerDemo {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("next()方法读取字符串:");
if(sc.hasNext()) {
String string = sc.next();
System.out.println("输入的数据为:"+string);
}
}
}
结果为:
next()方法读取字符串:
ki gang
输入的数据为:ki
eg.
import java.util.Scanner;
public class ScannerDemo {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("nextLine()方法读取字符串:");
if(sc.hasNext()) {
String string = sc.nextLine();
System.out.println("输入的数据为:"+string);
}
}
}
结果为:
nextLine()方法读取字符串:
ki gang
输入的数据为:ki gang
可以很明显的看到,next()方法遇到空格后,就停止输出了。
下面来总结一下两个方法的区别:
next()
一定要读取到有效字符后才可以结束输入。
对输入有效字符之前遇到的空白,next() 方法会自动将其去掉。
只有输入有效字符后才将其后面输入的空白作为分隔符或者结束符。
next() 不能得到带有空格的字符串。
nextLine():
以Enter为结束符,也就是说 nextLine()方法返回的是输入回车之前的所有字符。
可以获得空白。
读写文件
如前所述,一个流被定义为一个数据序列。输入流用于从源读取数据,输出流用于向目标写数据。
下图是一个描述输入流和输出流的类层次图。
下面将要讨论的两个重要的流是 FileInputStream 和 FileOutputStream:
FileInputStream
该流用于从文件读取数据,它的对象可以用关键字 new 来创建。
读取流的格式有:
//方法 1
InputStream f = new FileInputStream("C:/java/hello");
//方法 2
File f = new File("C:/java/hello");
InputStream out = new FileInputStream(f);
创建了InputStream对象,就可以使用下面的方法来读取流或者进行其他的流操作.
序号 | 方法及描述 |
---|---|
1 | public void close() throws IOException{} 关闭此文件输入流并释放与此流有关的所有系统资源。抛出IOException异常。 |
2 | protected void finalize()throws IOException {} 这个方法清除与该文件的连接。确保在不再引用文件输入流时调用其 close 方法。抛出IOException异常。 |
3 | public int read(int r)throws IOException{} 这个方法从 InputStream 对象读取指定字节的数据。返回为整数值。返回下一字节数据,如果已经到结尾则返回-1。 |
4 | public int read(byte[] r) throws IOException{} 这个方法从输入流读取r.length长度的字节。返回读取的字节数。如果是文件结尾则返回-1。 |
4 | public int available() throws IOException{} 返回下一次对此输入流调用的方法可以不受阻塞地从此输入流读取的字节数。返回一个整数值。 |
FileOutputStream
该类用来创建一个文件并向文件中写数据。
如果该流在打开文件进行输出前,目标文件不存在,那么该流会创建该文件。
创建格式:
//方法 1
OutputStream f = new FileOutputStream("C:/java/hello");
//方法 2
File f = new File("C:/java/hello");
OutputStream f = new FileOutputStream(f);
创建OutputStream 对象完成后,就可以使用下面的方法来写入流或者进行其他的流操作。
序号 | 方法及描述 |
---|---|
1 | public void close() throws IOException{} 关闭此文件输入流并释放与此流有关的所有系统资源。抛出IOException异常。 |
2 | protected void finalize()throws IOException {} 这个方法清除与该文件的连接。确保在不再引用文件输入流时调用其 close 方法。抛出IOException异常。 |
3 | public void write(int w)throws IOException{} 这个方法把指定的字节写到输出流中。 |
4 | public void write(byte[] w) 把指定数组中w.length长度的字节写到OutputStream中。 |
实例
下面是一个演示 InputStream 和 OutputStream 用法的例子:
import java.io.*;
public class FileStreamTest{
public static void main(String args[]){
try{
byte bWrite [] = {111,119,31,40,51};
OutputStream os = new FileOutputStream("test.txt");
for(int x=0; x < bWrite.length ; x++){
os.write( bWrite[x] ); // writes the bytes
}
os.close();
InputStream is = new FileInputStream("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");
}
}
}
结果为:
o w ( 3
上面的代码,以二进制写入数据,可能会出现乱码的情况,解决办法:
package file;
import java.io.*;
/**
* 创建文件(存在的话就不创建),在文件中写入数据,在读取出来,并且解决乱码问题
* @author qqg
*
*/
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("\r\n");
//换行
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();
// 关闭输入流,释放系统资源
}
}
结果为:
中文输入
English
Java中的目录
- mkdir( )方法创建一个文件夹,成功则返回true,失败则返回false。失败表明File对象指定的路径已经存在,或者由于整个路径还不存在,该文件夹不能被创建。
- mkdirs()方法创建一个文件夹和它的所有父文件夹。
eg.
import java.io.File;
/*
* 练习(三) 递归实现列出当前工程下所有.java文件
*/
public class Practice_03 {
public static void printJavaFiles(File dir) {
File next[] = dir.listFiles();
for (int i = 0; i < next.length; i++) {
/*for(int j = 0;j < lab; j++ ) {
System.out.print("|--");
}*/
if(next[i].isDirectory()) {
//是目录继续递归
printJavaFiles(next[i]);
}else {
String JavaFileName = ".java";
//获取文件名
String fileName = next[i].getName();
if(fileName.length()>=5) {
//截取文件名后 5 位 , 且避免大小写的原因,这里变成小写,判断是否是 .java
String subStr = fileName.substring(fileName.length()-5,fileName.length()).toLowerCase();
//System.out.println(subStr);
if(subStr.equals(JavaFileName)) { System.out.println(next[i].getName());
}
}
}
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println("当前目录下的.java文件有:");
printJavaFiles(new File("../IOTest_0805"));
}
}
结果为:
当前目录下的.java文件有:
CopyFile.java
CreateFile.java
Practice_01.java
Practice_02.java
Practice_03.java
Practice_04.java
Practice_05.java