IO复习学习
IO
流
在Java IO中,流是一个核心的概念。流从概念上来说是一个连续的数据流。你既可以从流中读取数据,也可以往流中写数据。流与数据源或者数据流向的媒介相关联。在Java IO中流既可以是字节流(以字节为单位进行读写),也可以是字符流(以字符为单位进行读写)。
类InputStream, OutputStream, Reader 和Writer
一个程序需要InputStream或者Reader从数据源读取数据,需要OutputStream或者Writer将数据写入到目标媒介中。以下的图说明了这一点:
[图片上传中...(image-42c2cd-1551613113798-0)]
InputStream和Reader与数据源相关联,OutputStream和writer与目标媒介相关联。
Java IO的用途和特征
Java IO中包含了许多InputStream、OutputStream、Reader、Writer的子类。这样设计的原因是让每一个类都负责不同的功能。这也就是为什么IO包中有这么多不同的类的缘故。各类用途汇总如下:
- 文件访问
- 网络访问
- 内存缓存访问
- 线程内部通信(管道)
- 缓冲
- 过滤
- 解析
- 读写文本 (Readers / Writers)
- 读写基本类型数据 (long, int etc.)
- 读写对象
当通读过Java IO类的源代码之后,我们很容易就能了解这些用途。这些用途或多或少让我们更加容易地理解,不同的类用于针对不同业务场景。
图谱IO的一些小例子
public void InputStreamTest(){
try {
//InputStream用于读取基于字节的数据,一次读取一个字节,这是一个InputStream的例子:
//字节流需要强转char
System.out.println("in InputStream : ");
InputStream inputStream = new FileInputStream("IOtest.txt");
int date = inputStream.read();
while (date != -1){
System.out.print((char) date);
date = inputStream.read();
}
System.out.print("\n");
inputStream.close();
}catch (Exception e){
System.out.println(e.getMessage() + " error");
}
}
public void InputStreamWithBuffer(){
try {
InputStream inputStream = new FileInputStream("IOtest.txt");
byte[] buffer = new byte[1024];
int data = inputStream.read(buffer);
while (data!=-1){
for (int i = 0; i < data; i++)
System.out.print((char) buffer[i]);
data = inputStream.read(buffer);
}
}catch (Exception e){
System.out.println(e.getMessage());
}
}
public void OutputTest() {
try {
byte bWrite[] = { 11, 21, 3, 40, 5 };
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
outputStream.write("hello world!!".getBytes());
byte[] buf = outputStream.toByteArray();
for (int i = 0; i < 11; i++)
System.out.print((char)buf[i]);
} catch (IOException e) {
System.out.print(e.getMessage());
}
}
read()
read()方法返回从InputStream流内读取到的一个字节内容(0~255),例子如下:
int data = inputstream.read();
你可以把返回的int类型转化成char类型:
char aChar = (char) data;
InputStream的子类可能会包含read()方法的替代方法。比如,DataInputStream允许你利用readBoolean(),readDouble()等方法读取Java基本类型变量int,long,float,double和boolean。
流末尾
如果read()方法返回-1,意味着程序已经读到了流的末尾,此时流内已经没有多余的数据可供读取了。-1是一个int类型,不是byte或者char类型,这是不一样的。
当达到流末尾时,你就可以关闭流了。
read(byte[])
InputStream包含了2个从InputStream中读取数据并将数据存储到缓冲数组中的read()方法,他们分别是:
int read(byte[])
int read(byte, int offset, int length)
一次性读取一个字节数组的方式,比一次性读取一个字节的方式快的多,所以,尽可能使用这两个方法代替read()方法。
read(byte[])方法会尝试读取与给定字节数组容量一样大的字节数,返回值说明了已经读取过的字节数。如果InputStream内可读的数据不足以填满字节数组,那么数组剩余的部分将包含本次读取之前的数据。记得检查有多少数据实际被写入到了字节数组中。
read(byte, int offset, int length)方法同样将数据读取到字节数组中,不同的是,该方法从数组的offset位置开始,并且最多将length个字节写入到数组中。同样地,read(byte, int offset, int length)方法返回一个int变量,告诉你已经有多少字节已经被写入到字节数组中,所以请记得在读取数据前检查上一次调用read(byte, int offset, int length)的返回值。
这两个方法都会在读取到达到流末尾时返回-1。
个人疑问
之前不知道字节流和字符的使用场景,知道写了一个图片上传的功能才有点清除。
字节流 FileInputStream FileOutputStream
字符流 FileReader FileWriter
字符流处理的单元为2个字节的Unicode字符,分别操作字符、字符数组或字符串,而字节流处理单元为1个字节,操作字节和字节数组。所以字符流是由Java虚拟机将字节转化为2个字节的Unicode字符为单位的字符而成的,所以它对多国语言支持性比较好!如果是音频文件、图片、歌曲,就用字节流好点,如果是关系到中文(文本)的,用字符流好点.
所有文件的储存是都是字节(byte)的储存,在磁盘上保留的并不是文件的字符而是先把字符编码成字节,再储存这些字节到磁盘。在读取文件(特别是文本文件)时,也是一个字节一个字节地读取以形成字节序列.
字节流可用于任何类型的对象,包括二进制对象,而字符流只能处理字符或者字符串; 2. 字节流提供了处理任何类型的IO操作的功能,但它不能直接处理Unicode字符,而字符流就可以。
public String saveImage(MultipartFile file) throws IOException {
int dotPos = file.getOriginalFilename().lastIndexOf(".");
if (dotPos < 0) {
return null;
}
String fileExt = file.getOriginalFilename().substring(dotPos + 1).toLowerCase();
if (!ToutiaoUtil.isFileAllowed(fileExt)) {
return null;
}
String fileName = UUID.randomUUID().toString().replaceAll("-", "") + "." + fileExt;
Files.copy(file.getInputStream(), new File(ToutiaoUtil.IMAGE_DIR + fileName).toPath(),
StandardCopyOption.REPLACE_EXISTING);
return ToutiaoUtil.TOUTIAO_DOMAIN + "image?name=" + fileName;
}
网友评论