Java Dev Notes - 4 - 关于IO

本文深入讲解Java中的输入输出流,包括基本的InputStream和OutputStream类及其使用方法,探讨如何利用这些类进行文件读写操作,并通过实例展示如何解决中文显示问题及正确使用ByteBuffer。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Java的输入输出流的基类为InputStream和OutputStream,处理字节流。

他们实现了基本的方法read()和write()是对一个字节的读写。

对于InputStream,读取的对象可以是

1.byte[]
2.String

3.File

4.管道

5.其他网络资源


** InputStream、OutputStream和InputStreamReader和OutputStreamWriter

Reader和Writer更善于处理unicode的字符流



另外一对基类为InputStreamReader和OutputStreamWriter, 由于处理字符流。


InputStreamReader(InputStream in)
          创建一个使用默认字符集的 InputStreamReader。
InputStreamReader(InputStream in,Charset cs)
          创建使用给定字符集的 InputStreamReader。
InputStreamReader(InputStream in,CharsetDecoder dec)
          创建使用给定字符集解码器的 InputStreamReader。
InputStreamReader(InputStream in,String charsetName)
          创建使用指定字符集的 InputStreamReader。


OutputStream同InputStream


IO重定向

	public void IORedirect() throws IOException{
		File file = new File("dat.log");
		if(!file.exists()) file.createNewFile();
		System.setIn(new FileInputStream(file));
		System.setOut(new PrintStream(new FileOutputStream(file)));
	}
	

然后在使用

System.out.println(i);

System.in.read(buffer);

时,就可以输出到文件了。   



读写文件


public class Hello {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		File file = new File("test.txt");
		try {
			file.createNewFile();
			FileOutputStream fos = new FileOutputStream(file);
			FileInputStream fis = new FileInputStream(file);
			DataOutputStream dos = new DataOutputStream(fos);
			DataInputStream dis = new DataInputStream(fis);
			
			dos.writeUTF("Hello World!");
			System.out.println(dis.readUTF());
			
			dos.close();
			dis.close();
			fos.close();
			fis.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}



使用ByteBuffer

test.txt中的内容

123456
dfsdfds
dfsdfsdfsd
ieirerw
dewerewirew
我如如我12


将文件读入ByteBuffer


	public static void main(String[] args) {
		try {
			ByteBuffer buffer = ByteBuffer.allocate(16);
			FileChannel fcin = new FileInputStream("test.txt").getChannel();
			while (fcin.read(buffer) != -1) {
				buffer.flip();
				int remainCount = buffer.remaining();
				for (int j = 0; j < remainCount; j++) {
					int i = buffer.get();
					System.out.print((char)i);
				}
				buffer.clear();
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}


运行结果:

123456
dfsdfds
dfsdfsdfsd
ieirerw
dewerewirew
????????12


问题:

无法显示中文。


之前我不是很了解为什么ByteBuffer要用一次flip()

我试着把上一段程序中的:

buffer.flip(); 

注释掉,再运行后得到以下的运行结果:

ire


原因:

文件在写以后读取,需要切换到读得模式,否则无法读取新的数据。



我们再次修改代码,使得代码可以输出中文,ByteBuffer可以返回内部封装的byte[]数组。

public static void main(String[] args) {

try {
ByteBuffer buffer = ByteBuffer.allocate(16);
FileChannel fcin = new FileInputStream("test.txt").getChannel();
while (fcin.read(buffer) != -1) {
buffer.flip();
System.out.write(buffer.array());
buffer.clear();
} 
} catch (Exception e) {
e.printStackTrace();
}
}



此次输出结果:

123456
dfsdfds
dfsdfsdfsd
ieirerw
dewerewirew
我如如我12ire


这次我们发现了什么?多出了三个字母ire,那是因为我们把整个buffer都输出了,而并不是整个buffer都是有效的,后一部分是上次缓存读入时残存的数据。

** 无论在使用和自己实现buffer时我们都要在输入中注意溢出问题,输出是注意有效数据的问题,当然有效输入取决于读入时候对于有效数据的记录。


public static void main(String[] args) {
try {
ByteBuffer buffer = ByteBuffer.allocate(16);
FileChannel fcin = new FileInputStream("test.txt").getChannel();
while (fcin.read(buffer) != -1) {
buffer.flip();
int remainCount = buffer.remaining();
System.out.write(buffer.array(),0,remainCount);
buffer.clear();
} 
} catch (Exception e) {
e.printStackTrace();
}
}

这下我们得到正确的输出了:

123456
dfsdfds
dfsdfsdfsd
ieirerw
dewerewirew
我如如我12




关于文件操作


输出当前目录下的所有文件:

public static void main(String[] args) {
		File path = new File(".");
		String[] list;
		list = path.list();
		for(int i=0; i<list.length;i++){
			System.out.println(list[i]);
		}
	}

输出结果:

.classpath
.project
.settings
bin
src
test.txt


那如果是上层文件呢?

	public static void main(String[] args) {
		File path = new File("..");//该动该句显示上层文件中的所有文件
		String[] list;
		list = path.list();
		for(int i=0; i<list.length;i++){
			System.out.println(list[i]);
		}
	}

那如果是再上上层呢?

那么请使用getParentFile()的方法



文件过滤器


过滤文件名

public class Test {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		File path = new File(".");
		String[] list;
		list = path.list(new DirFilter());
		for(int i=0; i<list.length;i++){
			System.out.println(list[i]);
		}
	}	
}

class DirFilter implements FilenameFilter{

	@Override
	public boolean accept(File dir, String name) {
		if(name.startsWith(".")) return true;
		else return false;
	}
}

输出结果:

.classpath
.project
.settings


过滤文件


public class Test {

	public static void main(String[] args) {
		File path = new File(".");
		File[] list;
		list = path.listFiles(new DirFilter());
		for(int i=0; i<list.length;i++){
			System.out.println(list[i].getName());
		}
	}	
}

class DirFilter implements FileFilter{

	@Override
	public boolean accept(File pathname) {
		if(pathname.isDirectory()) return true;
		else return false;
	}

}

输出结果:

.settings
bin
src







评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值