写在前面,本文章的目标是基本覆盖JavaIO的全部内容,然后,文章还是以例子为主,因为我觉得学以致用才是真,写出来的代码才是自己的代码,而不是看的。
学习Java的IO流,首先就是学习文件(也就是File类)。
文件类
下面我们来示例一下如何通过File类创建一个新文件。
import java.io.*; public class Hello{ public static void main(String[] args) { File f=new File("D:\\hello.txt"); try{ f.createNewFile(); }catch (Exception e) { e.printStackTrace(); } } }
【运行结果】:
程序运行之后,在d盘下会有一个名字为hello.txt的文件。
通过创建File类的对象,可以获取到对象的许多操作:
比如说删除一个文件:
f.delete();
创建一个文件夹:
f.mkdir();
等等……
然后我还了解到一个我认为是很必要的一个习惯:
就是改写
File f=new File("D:\\hello.txt");
中文件路径的写法;
首先我们要知道File类的两个常量:
此处可能有些同学认为,我在Windows下直接使用"\"分割不就行了吗?这当然是可以的,但是到了Linux下就不是"\"了,所以为了我们代码的健壮性和跨平台性,推荐使用这些常量,其实因为多写不了几行。
现在我们使用上面的方法改写之前的代码:
import java.io.*; public class Hello{ public static void main(String[] args) { String fileName="D:"+File.separator+"hello.txt"; File f=new File(fileName); try{ f.createNewFile(); }catch (Exception e) { e.printStackTrace(); } } }
看吧,只是多了一行而已,但是代码的跨平台性就增强了许多。
字节流和字符流
学习了简单的File类的知识,现在我们就可以在其之上进行更多的操作了。
比如说写入数据,从文件中读取数据。
下面是一个小例子:
import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; public class IOStream { /** * 读取函数 * @param filename */ public void read(String filename){ File f=new File(filename); try { InputStream ins=new FileInputStream(f); int i=ins.read(); while(i!=-1){ System.out.println("读取的字节码为:"+i); i=ins.read(); } ins.close(); } catch (IOException e) { e.printStackTrace(); } } /** * 输出函数 * @return */ public String print(String filename){ File f=new File(filename); String s=""; try { @SuppressWarnings("resource") InputStream ins=new FileInputStream(f); byte[] printtest=new byte[ins.available()];//ins.available是取得输入流的长度。 ins.read(printtest);//与ins.read();不一样。这个是从输入流中读取数据并把它写到byte[]中。 s=new String(printtest); System.out.println(s); } catch (FileNotFoundException e) { e.printStackTrace(); return "Error!"; } catch (IOException e) { e.printStackTrace(); return "Error!"; } return s; } /** * 写入函数 * @param message */ public void write(String message){ try { OutputStream outs=new FileOutputStream("F:\\test.txt"); //输出流中的数据“流”入到路径所在的文件中。 byte[] iowrite=message.getBytes(); outs.write(iowrite); //是从iowrite中读取数据并写入到输出流中。 outs.flush(); System.out.println("写入成功!"); outs.close(); }catch (IOException e) { e.printStackTrace(); } } /** * 加密函数 * @param args */ public void encrypt(String message){ int i,j; try { byte[] iowrite=message.getBytes(); int size=iowrite.length; byte[] msg1=new byte[size/2]; OutputStream outs=new FileOutputStream("F:\\msg1.txt"); for(i=0;i<(size/2);i++){ msg1[i]=(byte) (iowrite[i]+1); } outs.write(msg1); outs.flush(); outs.close(); System.out.println("成功一半!"); OutputStream newouts=new FileOutputStream("F:\\msg2.txt"); byte[] msg2=new byte[size-(size/2)]; for(j=0;i<size;i++,j++){ msg2[j]=(byte) (iowrite[i]-1); } newouts.write(msg2); newouts.flush(); System.out.println("写入成功!"); newouts.close(); }catch (IOException e) { e.printStackTrace(); } } /** * 解密函数 * @param args */ public void discrypt(String msg1,String msg2){ int i,j; try { byte[] msg_1=msg1.getBytes(); byte[] msg_2=msg2.getBytes(); int size_1=msg_1.length; int size_2=msg_2.length; byte[] write=new byte[size_1+size_2]; OutputStream outs=new FileOutputStream("F:\\msg.txt"); for(i=0;i<size_1;i++){ msg_1[i]=(byte) (msg_1[i]-1); write[i]=msg_1[i]; } for(i=size_1,j=0;j<size_2;j++,i++){ msg_2[j]=(byte) (msg_2[j]+1); write[i]=msg_2[j]; } outs.write(write); outs.flush(); System.out.println("写入成功!"); outs.close(); }catch (IOException e) { e.printStackTrace(); } } public static void main(String[] args) { @SuppressWarnings("unused") String filename="F:\\IOStream.java"; String msg_1="F:\\msg1.txt"; String msg_2="F:\\msg2.txt"; IOStream test =new IOStream(); test.discrypt(test.print(msg_1),test.print(msg_2)); } }
这上面还执行了一个字节层面的数据加密和解密,加密是将所有的字节码分为两份,一份字节码加一,一份字节码减一,然后分开存为两份文件。解密当然就是加密的反向操作啦!
然后我要承认一个错误,就是为了方便,我还是直接写的路径,没有用常量(0.0)。
然后写入数据还可以直接用Writer类:
/** * 字符流 * 写入数据 * */ import java.io.*; public class hello{ public static void main(String[] args) throws IOException { String fileName="D:"+File.separator+"hello.txt"; File f=new File(fileName); Writer out =new FileWriter(f); String str="hello"; out.write(str); out.close(); } }
如果你想向文件中追加内容,可以使用将上面的声明out的那一行换为:
Writer out =new FileWriter(f,true);
同样的,用OutputStream类时,也可以改成如下代码来执行此操作:
OutputStream outs=new FileOutputStream("F:\\test.txt",true);
如果想在文件中换行的话,需要使用“\r\n”;
比如将str 变为String str="\r\nhello";
这样文件追加的内容就会换行了。
那么相对称的,我们可以用Reader类来读取数据:
/** * 字符流 * 从文件中读出内容 * */ import java.io.*; public class hello{ public static void main(String[] args) throws IOException { String fileName="D:"+File.separator+"hello.txt"; File f=new File(fileName); char[] ch=new char[100]; Reader read=new FileReader(f); int count=read.read(ch); read.close(); System.out.println("读入的长度为:"+count); System.out.println("内容为"+new String(ch,0,count)); } }
读者可能会困扰InputStream(OutputStream)和Reader(Writer)的区别,那我们下面就来分析一下:
Reader(Writer)支持16位的Unicode字符输出(输入),而InputStream(OutputStream)支持8位的字符输出。
InputStream(OutputStream)和Reader(Writer)分别是I/O库提供的两套平行独立的等级机构。
InputStream和OutputStream是用来处理8位元的流。Reader和Writer是用来处理16位元的流。
而在Java语言中,byte类型是8位的,char类型是16位的,所以在处理中文时需要用Reader和Writer。
值得说明的是,在这两种等级机构下,还有一道桥梁InputStreamReader、OutputStreamWriter负责进行InputStream到Reader的适配以及OutputStream到Writer的适配。
java.io.Reader和java.io.InputStream组成了Java的输入类。Reader用于读入16位字符,也就是Unicode编码的肌肤;而InputStream用于读入ASCLL字符和二进制数据。
在Java中,有不同类型的Reader输入流对应不同的数据源:
FileReader 用于从文件输入;
CharArrayReader 用于从程序的字符数组输入;
StringReader 用于从程序中的字符串输入;
PipedReader 用于读取从另一个线程中的 PIpedWriter 写入管道的数据。
相应的也有不同类型的 InputStream 输入流对应于不同的数据源:
FileInputStream;
ByteArrayInputStream;
StringBufferInputStream;
PipedInputStream。
另外,还有两种没有对应 Reader 类型的 InputStream 输入流:
Socket 用于套接字;
URLConnection 用于 URL 连接。
这两个类使用 getInputStream()来读取数据。
相应的,java.io.Writer和java.io.OutputStream 也有类似的区别。
提醒一下,当用read()方法读到文件末尾的时候会返回-1,正常情况下是不会返回-1的。
关于字节流和字符流的区别
实际上字节流在操作的时候本身是不会用到缓冲区的,是文件本身的直接操作的,但是字符流在操作的 时候下后是会用到缓冲区的,是通过缓冲区来操作文件的。
读者可以试着将上面的程序的最后一行关闭文件的代码注释掉,然后运行程序看看。你就会发现使用字节流的话,文件中已经存在内容,但是使用字符流时,文件中还是没有内容的,这个时候就要刷新缓冲区。
使用字节流好还是字符流好呢?
答案是字节流。首先因为硬盘上的所有文件都是以字节的形式进行传输或者保存的,包括图片、音乐等内容。但是字符只是在内存中才会存在,所以在开发中,字节流使用广泛。
管道流
管道流主要可以进行两个线程之间的通信。
PipedOutputStream 管道输出流
PipedInputStream 管道输入流
下面我们来验证一下管道流:
/** * 验证管道流 * */ import java.io.*; /** * 消息发送类 * */ public class Send implements Runnable{ private PipedOutputStream out=null; public Send() { out=new PipedOutputStream(); } public PipedOutputStream getOut(){ return this.out; } public void run(){ String message="Hello , Java"; try{ out.write(message.getBytes()); }catch (Exception e) { e.printStackTrace(); }try{ out.close(); }catch (Exception e) { e.printStackTrace(); } } } /** * 接受消息类 * */ class Recive implements Runnable{ private PipedInputStream input=null; public Recive(){ this.input=new PipedInputStream(); } public PipedInputStream getInput(){ return this.input; } public void run(){ byte[] b=new byte[1000]; int len=0; try{ len=this.input.read(b); }catch (Exception e) { e.printStackTrace(); }try{ input.close(); }catch (Exception e) { e.printStackTrace(); } System.out.println("接受的内容为 "+(new String(b,0,len))); } } /** * 测试类 * */ class hello{ public static void main(String[] args) throws IOException { Send send=new Send(); Recive recive=new Recive(); try{ //管道连接 send.getOut().connect(recive.getInput()); }catch (Exception e) { e.printStackTrace(); } new Thread(send).start(); new Thread(recive).start(); } }
运行结果:
接受的内容为 Hello,Java
数据操作流DataOutputStream、DataInputStream类
import java.io.DataOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; public class DataOutputStreamDemo{ public static void main(String[] args) throws IOException{ File file = new File("d:" + File.separator + "hello.txt"); char[] ch = { 'A', 'B', 'C' }; DataOutputStream out = null; out = new DataOutputStream(new FileOutputStream(file)); for(char temp : ch){ out.writeChar(temp); } out.close(); } }
A B C
现在我们在上面的例子的基础下,使用DataInputStream读出内容:
mport java.io.DataInputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; public class DataOutputStreamDemo{ public static void main(String[] args) throws IOException{ File file = new File("d:" + File.separator + "hello.txt"); DataInputStream input = new DataInputStream(new FileInputStream(file)); char[] ch = new char[10]; int count = 0; char temp; while((temp = input.readChar()) != 'C'){ ch[count++] = temp; } System.out.println(ch); } }
输出结果:A B
I/O就先和大家论述到这里,在之后学习的更加完善时,我会及时跟进,增加此博文的内容,欢迎大家关注我,也欢迎大家提出意见和建议。
相关推荐
### JAVA IO流概念及其应用详解 #### 一、JAVA为何引入流的概念? 在JAVA中,引入流的概念主要是为了实现对各种类型数据的高效处理。在实际应用中,无论是从网络中传输数据还是从本地文件中读取数据,亦或是与用户...
IO流被设计为双工通道,既可以进行输入操作,也可以进行输出操作。Java的IO流体系结构复杂,但有规律可循,主要包括字节流和字符流两大类。 1. **字节流** - **字节流基类**:InputStream和OutputStream是所有字节...
在Java中,IO流操作是用于处理输入与输出的抽象机制,它提供了在不同的数据源和目标之间传输数据的手段。流的概念最早起源于UNIX系统中的管道概念,是一个连续的数据流,可以理解为水流,从源端流向目的端。 一、流...
### 自己总结的IO流操作 #### 知识点概览 本文档主要涉及Java中的IO流操作,包括输出流(OutputStream)、输入流(InputStream)、对象流(ObjectOutputStream与ObjectInputStream)、字符输出流(Writer)及字符...
在IO流操作中,我们还需要了解一些关键概念: - **管道流(Piping Stream)**:允许流之间的连接,使得一个流的输出可以作为另一个流的输入。 - **转换流(Wrapper Stream)**:如Buffered开头的流,它们不改变数据...
Java的IO流体系结构是Java开发中非常重要的组成部分,它不仅涵盖了基本的输入输出操作,还提供了高级的并发处理机制。无论是初学者还是经验丰富的开发者,掌握这些基础知识都将极大地提高编写高效、健壮的Java程序的...
C#中的文本IO流是一种处理输入/输出操作的技术,特别用于读写文本文件。这个领域的核心在于抽象类`Stream`,它是所有流操作的基础。`Stream`类提供了对各种存储介质(如磁盘、内存等)进行数据读写的抽象接口,使得...
在这个“javaIO流基础.zip”压缩包中,我们能看到一系列与文件上传和下载相关的Java代码示例,涵盖了多种IO流类型及其用法。 首先,`TestFileOutputStream.java`和`TestFileInputStream.java`涉及到的是文件输入流...
下面将详细探讨Java IO流的原理及其在开发记事本应用中的运用。 首先,Java的IO流分为两大类:字节流和字符流。字节流处理的是8位的字节,适用于处理任何类型的数据,如图片、音频、视频等;而字符流处理的是16位的...
了解和掌握Java IO流的概念、分类及其相互关系,对于编写高效、稳定的程序至关重要。通过学习和实践,开发者能够灵活运用各种流类,实现复杂的数据传输和处理任务。同时,NIO的使用也是现代Java开发中不可或缺的技能...
总的来说,Java的IO流机制是高度灵活和强大的,能够适应各种不同的数据传输需求,无论是简单的文件操作还是复杂的网络通信。通过选择合适的流类型和组合使用过滤流,开发者可以实现高效且易维护的数据处理代码。
异常处理在IO流操作中尤为重要,因为文件可能存在或不存在,网络连接可能出现问题,或者其他各种错误可能导致流操作失败。因此,通常会在IO操作中使用`try-catch`块来捕获和处理可能出现的异常。 总结: Java的异常...
Java IO流和Socket是Java编程语言中用于处理输入输出和网络通信的重要概念。在这个示例中,我们将深入探讨如何利用Java IO流与Socket实现简单的文本传输。对于初学者来说,理解这两个概念及其交互是非常关键的。 ...
JAVA IO流是Java编程中用于处理输入输出操作的重要工具。IO流主要分为两大类,即输入流(Input Streams)和输出流(Output Streams),它们用于读取或写入数据到不同的数据源,比如文件、网络连接或内存中的字节数组。在...
### Java IO流详解 #### 一、流的概述与分类 在Java中,流是一种抽象概念,用于描述数据从一个地方传输到另一个地方的过程。它主要用于处理数据输入和输出,例如从磁盘读取文件、向网络发送数据或从键盘接收用户...
以下是一些关键的IO流类及其在Android中的应用: 1. **FileInputStream** 和 **FileOutputStream**:这两个类用于读取和写入文件。通过`openFileInput()`和`openFileOutput()`方法,我们可以获取到对应的...
本篇文章将详细探讨C#中的部分IO流及其应用实例,帮助开发者更好地理解和运用这一关键技术。 首先,C#中的IO流分为两大类:字节流(Byte Stream)和字符流(Character Stream)。字节流处理的是原始的二进制数据,...
本文档将详细梳理Java IO流的基本概念、分类、常用类及其应用场景。 一、基本概念 1. 流:在Java中,流是一组有序的数据序列,可以是从内存到硬盘,也可以是从硬盘到内存,或者在网络间传输。流的概念抽象了数据...
### Java的IO流操作 #### 一、Java IO流概述 在Java中,输入/输出(Input/Output,简称IO)流是进行数据读写的基础技术。Java的IO流主要包含两大类:字节流(byte stream)和字符流(character stream)。字节流...
在这个话题中,我们将深入探讨Java中的七种主要IO流及其基本用法,包括BufferedWriter、FileReader、转换流(InputStreamReader/OutputStreamWriter)以及缓存流(BufferedInputStream/BufferedOutputStream)。...