他是一种数据的流,从源头流到目的地。好比文件的拷贝,输入流从文件中读取到进程,输出流从进程写入文件中。html
字节流在JDK1.0的时候就被引入了,用以操做字符集类型为ASCII的数据。为了可以操做Unicode类型的数据,JDK1.1引入了字符流。linux
咱们知道,计算机内部全部的信息最终都是以字节的形式存储的,一个字节有8位,每一位上都是0或者1。那么总共有256种组合方式。在上世纪60年代,美国制定了一套英语字符与二进制位之间的关系。这种关系被称为ASCII码,他一共规定了128个字符的编码,好比空格是32,大写的A是65。这128个字符只占用了一个字节的后七位,第一位设置为0。
可是世界上的语言不止包括128个字符,而且相同的ASCII码也会被翻译成不一样的字符。所以,想打开一个文本文件,就必须知道他的编码方式。这时候Unicode就出现了,他将世界上全部的符号都归入其中,每一个符号都给予一个编码,那么乱码的问题就解决了。
可是Unicode也存在问题,那就是只规定了符号的代码,并无规定二进制代码如何存储。好比说某个字符占两个字节,那么计算机怎么知道他是表明两个占一个字节的字符仍是一个占两个字节的字符呢?
互联网的普及,迫切须要一种统一的编码方式。UTF-8就是Unicode使用最普遍的一种实现,还有UTF-16(用两个或四个字节表示一个字符),UTF-32(用四个字节表示一个字符)。UTF-8最大的特色就是采用一种变长的编码方式存储字符。
UTF-8的编码规则:
面试
1.对于单字节的符号,字节的第一位设为0,后面7位为这个符号的 Unicode 码。所以对于英语字母,UTF-8 编码和 ASCII 码是相同的。缓存
2.对于n字节的符号(n > 1),第一个字节的前n位都设为1,第n + 1位设为0,后面字节的前两位一概设为10。剩下的没有说起的二进制位,所有为这个符号的 Unicode 码。
bash
举例:
对于单字节字符:0XXXXXXX
对于双字节字符:110XXXXXX | 10XXXXXX
对于三字节字符:1110XXXXX | 10XXXXXX | 10XXXXXX
网络
举例:app
对于字节流,能够采用BufferedInputStream或者BufferedOutputStream。
对于字符流,能够采用BufferedReader或者BufferedWriter。工具
这是在读写文件时用到的两个类,对于小文件他们的性能表现的还不错,可是对于大文件时,尽可能使用BufferedReader或者BufferedWriter。性能
System是Java.lang包下的一个final类,out是其中的一个PrintStream类型的静态成员变量,println是他的一个方法。ui
引用Java doc中的描述:
An abstract representation of file and directory pathnames.
-对文件及文件路径的抽象表明。意思就是File类只表明这个文件的路径,而不表明文件对象。在Java7引入的nio包中的Path类与io中的File本质上是一个东西。(Path.toFile()=File.toPath(),两者之间能够相互转换)。
NIO被翻译为(new IO)或者(Non-blocking IO-非阻塞的IO),在Java7的时候被引入,与IO直接磁盘读写不一样的是,NIO采用缓存的方法对文件进行操做。
\r\n
,在Linux系统中是\n
。代码以下:
public static void getByteFromWeb() {
CloseableHttpClient httpClient = HttpClients.createDefault();
HttpGet httpGet = new HttpGet("https://www.baidu.com/");
try (CloseableHttpResponse httpResponse = httpClient.execute(httpGet)) {
//注意,我这里并无设置编码字符集
InputStream inputStream = httpResponse.getEntity().getContent();
int byteToInt;
while ((byteToInt = inputStream.read()) != -1) {
System.out.print((char) byteToInt);
}
}catch (Exception e){
throw new RuntimeException(e);
}
}
复制代码
打印结果以下:
InputStreamRead
的构造方法,为InputStream设置字符集:
InputStreamReader inputStream = new InputStreamReader(httpResponse.getEntity().getContent(),Charsets.UTF_8);
复制代码
这时候再打印结果就能看到咱们想要的情形:
代码以下:
public static void getByteFromProcess(){
try {
ProcessBuilder processBuilder = new ProcessBuilder("{commend}");
Process start = processBuilder.start();
InputStreamReader inputStream = new InputStreamReader(start.getInputStream(),Charsets.UTF_8);
int byteToInt;
while ((byteToInt = inputStream.read())!=-1){
System.out.print((char)byteToInt);
}
}catch (Exception e){
throw new RuntimeException(e);
}
}
复制代码
经过这个发现好玩的事情,在new ProcessBuilder("{commend}")
中写入:
("cmd.exe", "/C", "start")
复制代码
能够经过代码启动cmd
,也能够经过
("C:\\Windows\\System32\\calc.exe")
复制代码
启动本机的计算器。
使用commons-io包里面的FileUtils.writeLines()方法,引入Maven依赖后:
public static void writeLinesToFile1(List<String> lines, File file) {
try {
FileUtils.writeLines(file, lines);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
复制代码
使用BufferedWriter.write()方法逐行写入:
public static void writeLinesToFile2(List<String> lines, File file) {
try {
Writer writer = new FileWriter(file);
BufferedWriter bufferedWriter = new BufferedWriter(writer);
for (String s : lines
) {
bufferedWriter.write(s);
bufferedWriter.write("\n");
}
bufferedWriter.close();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
复制代码
使用Files工具中的write()方法整个写入:
public static void writeLinesToFile3(List<String> lines, File file) {
try {
Files.write(file.toPath(), lines);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
复制代码
使用IOUtils.writeLines()整个写入:
public static void writeLinesToFiles4(List<String> lines, File file) {
try {
// 须要设置append为true,将字节写入文件中
Writer writer = new FileWriter(file, true);
IOUtils.writeLines(lines, null, writer);
// OutputStream outputStream = new FileOutputStream(file);
// IOUtils.writeLines(lines, null, outputStream, Charset.defaultCharset());
} catch (Exception e) {
throw new RuntimeException(e);
}
}
复制代码
使用InputStream.read()方法逐个读取:
public static List<String> readFile1(File file) {
List<String> list = new ArrayList<>();
//使用StringBuilder将获取的单个字符拼接成字符串
StringBuilder stringBuilder = new StringBuilder();
try {
InputStream inputStream = new FileInputStream(file);
int byteToInt;
while ((byteToInt = inputStream.read()) != -1) {
char c = (char) byteToInt;
if (c != '\r' && c != '\n') {
stringBuilder.append((char) byteToInt);
} else {
if (!stringBuilder.toString().equals("")) {
list.add(stringBuilder.toString());
stringBuilder.delete(0, stringBuilder.length());
}
}
}
} catch (Exception e) {
throw new RuntimeException(e);
}
return list;
}
复制代码
使用BufferReader.readLine()方法逐行读取:
public static List<String> readFile2(File file) {
List<String> list = new ArrayList<>();
try {
BufferedReader bufferedReader = new BufferedReader(new FileReader(file));
String s;
while ((s = bufferedReader.readLine()) != null) {
list.add(s);
}
} catch (Exception e) {
throw new RuntimeException(e);
}
return list;
}
复制代码
使用Files工具中的readAllLines()方法整个读取:
public static List<String> readFile3(File file) {
List<String> list;
try {
list = Files.readAllLines(file.toPath());
} catch (IOException e) {
throw new RuntimeException(e);
}
System.out.println();
return list;
}
复制代码
使用FileUtils.readFileToString()方法整个文档读取:
public static List<String> readFile4(File file){
List<String> list = new ArrayList<>();
try {
list.add(FileUtils.readFileToString(file, Charset.defaultCharset()));
} catch (IOException e) {
throw new RuntimeException(e);
}
return list;
}
复制代码
使用IOUtils.readLines()方法整个文档读取:
public static List<String> readFile5(File file) {
try {
InputStream inputStream = new FileInputStream(file);
return IOUtils.readLines(inputStream, Charset.defaultCharset());
} catch (IOException e) {
throw new RuntimeException(e);
}
}
复制代码