0802(022天 输入输出流02 字符流+字节流)
每日一狗(田园犬西瓜瓜)
输入输出流02 字符流+字节流
文章目录
1. System终端输入输出
System类是Java语言中一个功能强大、非常有用的类,它提供了标准输入/输出及运行时的系统信息
- System类不能创建对象,也就是说,System类的所有属性和方法都是静态的,引用时要以System作为前缀,这是个工具类
- System.in与System.out是System类的两个静态属性,分别对应了系统的标准输入/输出流
- System.out:把输出送到缺省的显示(通常是显示器),是PrintStream的对象
- System.in:从标准输入获取输入(通常是键盘),是InputStream的对象
- System.err:把错误信息送到缺省的显示,是PrintStream的对象
1.1 System.in
System.in.read()
只从终端读取一个字符
package com.yang2;
import java.io.IOException;
/*
* 题目:用户在键盘依次输入若干个数字,
*
* 每输入一个数字都需要按回车键确认,
*
* 最后在键盘输入一个非数字字符串结束整个输入操作过程。
*
* 程序将计算出这些数的和以及平均值。
*/
public class T01 {
public static void main(String[] args) throws IOException {
int sum = 0;
int count = 0;
while (true) {
String strnum = readData();
if ("quit".equals(strnum)) {
break;
}
if (strnum != null && strnum.trim().length() > 0) {
sum += Integer.parseInt(strnum);
count++;
}
}
String ss = sum + "|" + (sum / count);
System.out.println(ss);
byte[] arr = ss.getBytes();
System.out.write(arr);
}
public static String readData() throws IOException {
byte[] arr = new byte[10];
int len = 0;
while (true) {
int kk = System.in.read();
if (kk == '\r' || kk == '\n') {
break;
}
arr[len++] = (byte) kk;
}
return new String(arr, 0, len);
}
}
/* 测试输出
123
456
quit
579|289
*/
1.2 System.out
System.out.write(byte[]);
System.out.write(byte[], index, len ); 从数组的index开始写,写出len个字节
package com.yang2;
import java.io.IOException;
public class test {
/*
* 578 + + (sum / count)
*
* 578 + + (sum / count)
*/
public static void main(String[] args) throws IOException {
String ss = "578 + + (sum / count)";
System.out.println(ss);
byte[] arr = ss.getBytes();
System.out.write(arr);
}
}
1.3 System.err
这个输出到终端的字符是红色的
System.err.println("偶数");
1.4 字符串格式化
String.format(String 字符格式, 按照顺序往里填)
2. 字节流
啥文件都能操作
2.1 InputStream基本输入类
- read():int 返回一个整形,-1则文件已经到末尾了
- read(byte[]):int 返回一个整形,表示字节数组中的的字符的地多少个前都是文件内容,返回-1则表示文件已经空了
需求:读取一个文件的内容并输出所有的数据(没有汉字,由于字节流读取的最小单位是字节,但是一般情况下一个汉字字符最少都要两个字节,所以为导致乱码的生成)
package com.yan1;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
public class Test2 {
public static void main(String[] args) {
try (InputStream is = new FileInputStream("d:/out/abc.txt")) {
int kk = -1;
while ((kk = is.read()) != -1) {
System.out.print((char) kk);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
2.2 OutputStream基本输出类
- write(int): 写入一个字节数据
- write(byte b[]): 将一个字节类型的数组中的数据写入到输出流
- write(byte[], offset, lenget): 将一个字节类型的数组中的从指定位置offset开始 的length个字节写入到输出流
需求:文件的拷贝(这里由于是单字节转移,所以这个文件中的汉字其实可以展示,他们的文件编辑器的编码字符集都是同的,但是读取的话读取进来的还是单子字节一个字节的汉字肯定就是乱码呀)
package com.test;
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 T01 {
public static void main(String[] args) throws FileNotFoundException, IOException {
try (
InputStream in = new FileInputStream(
"D:\\桌面\\20220802\\src\\com\\yan1\\Test2.java");
OutputStream out = new FileOutputStream(
"D:\\桌面\\output.txt")) {
int len = 0;
while ((len = in.read()) > 0) {
System.out.print((char) len);
out.write(len);
}
}
}
}
2.3 相关的子类
- FileInputStream、FileOutputStream 顺序读取文件
- PipedInputStream、PipedOutputStream 管道
- ByteArrayInputStream、ByteArrayOutputStream 内存读写
- FilterInputStream、FilterOutputStream 过滤流(有多线程同步)
- DataInputStream、DataOutputStream 对数据类型读写,有多线程同步
- BufferedInputStream、BufferedOutputStream 缓冲类型读写
3. 字符流
主要用于操作文本文件,由于这个单次读取的是一个字符,所以不会出现像上面那种乱码的情况,操作的也就是一个字符而不是一个字节。
但是这个也需要注意编码问题java中默认的编码字符集为UTF-8,但是win中默认的文本文件的编码字符为ANSI及GBK编码,还是会存在部分字符出现乱码情况的
3.1 Reader
- read():int 只读取一个字符
- read(char[]):int 可以读取多个字符,返回值为都到哪里了
package com.yang3;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
/*
* 这里是中文读取测试
*/
public class T01 {
public static void main(String[] args) throws FileNotFoundException, IOException {
try (Reader in = new FileReader("src/com/yang3/T01.java")) {
int kk = 0;
while ((kk = in.read()) > 0) {
System.out.print((char) kk);
}
}
}
}
3.2 Writer
out.write(char) ; 写入单个字符
out.write(char[] ); 将整字符数组写入
out.wreite(char[], index, len); 将字符数组从index写入l长度
package com.yang3;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.util.Scanner;
public class T03 {
public static void main(String[] args) throws IOException {
try (Writer out = new FileWriter("D:\\桌面\\a.txt")) {
Scanner sc = new Scanner(System.in);
while (true) {
String ss = sc.nextLine();
if ("quit".equals(ss)) {
break;
}
char[] arr = ss.toCharArray();
out.write(arr, 0, 2);
for (int i = 0; i < arr.length; i++) {
out.write(arr[i]);
}
out.write('\n');
}
sc.close();
}
}
}
4 练习题:
课后练习题
1、练习1:使用字节流读取一个文本文件,并显示其内容
package com.test;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
public class Test01 {
public static void main(String[] args) throws FileNotFoundException, IOException {
try (InputStream in = new FileInputStream("src/com/test/Test01.java")) {
while (true) {
int len = in.read();
if (len == -1) {
break;
}
System.out.print((char) len);
}
}
}
}
2、用户在键盘依次输入若干个数字,每输入一个数字都需要按回车键确认,最后在键盘输入一个非 数字字符串结束整个输入操作过程。程序将计算出这些数的和以及平均值。
用来读写外设字符的,它们都是字节流。如果编程人员愿意,可以用基于字符的流来包装它们
package com.test;
public class Test02 {
public static void main(String[] args) {
// System.out.println(input().length());
test();
}
public static void test() {
int sum = 0;
int count = 0;
while (true) {
String numS = input();
if ("quit".equals(numS)) {
break;
}
// 这里要注意他会紧接着返回一个\n的一个空串
if ("".equals(numS)) {
continue;
}
sum += Integer.parseInt(numS.trim());
count++;
}
System.out.println("和为=" + sum + " 平均数为=" + (sum / count));
}
public static String input() {
String resStr = "";
while (true) {
int tmp = 0;
try {
tmp = System.in.read();
} catch (Exception e) {
// TODO: handle exception
}
if (tmp == '\r' || tmp == '\n') {
break;
}
resStr = resStr + (char) tmp;
}
return resStr;
}
}
3、文件夹的拷贝 cp 文件夹的移动 mv
package com.test;
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;
import java.util.Arrays;
public class Test03 {
static String target = "src\\\\data";
static String soure = "src\\\\com\\test";
static String target1 = "data2";
static String soure1 = "data";
public static void main(String[] args) throws FileNotFoundException, IOException {
// traverse(new File("src/com/test"));
mv(new File("data"));
System.out.println(Arrays.toString(new File("data").listFiles()));
}
public static void mv(File file) throws FileNotFoundException, IOException {
if (file.exists()) {
String newPath = file.getAbsolutePath().replaceAll(soure1, target1);
File newFile = new File(newPath);
if (file.isDirectory()) {
if (newFile.exists()) {
newFile.mkdirs();
}
File[] fs = file.listFiles();
if (fs != null && fs.length >= 0) {
for (File f : fs) {
mv(f);
}
}
} else if (file.isFile()) {
try (InputStream in = new FileInputStream(file); OutputStream out = new FileOutputStream(newFile)) {
int tmp = 0;
while ((tmp = in.read()) != -1) {
out.write(tmp);
}
}
}
file.delete(); // 在干完事情之后将文件删除
}
}
public static void traverse(File file) throws FileNotFoundException, IOException {
if (file.exists()) {
String newPath = file.getAbsolutePath().replaceAll(soure, target);
File newFile = new File(newPath);
if (file.isDirectory()) {
if (newFile.exists()) {
newFile.mkdirs();
}
File[] fs = file.listFiles();
if (fs != null && fs.length >= 0) {
for (File f : fs) {
traverse(f);
}
}
} else if (file.isFile()) {
try (InputStream in = new FileInputStream(file); OutputStream out = new FileOutputStream(newFile)) {
int tmp = 0;
while ((tmp = in.read()) != -1) {
out.write(tmp);
}
}
}
}
}
}
4、编写一个程序,读取文件test.txt的内容并在控制台输出。如果源文件不存在,则显示相应的错误 信息。
5、编写一个程序实现如下功能,从当前目录下的文件fin.txt中读取80个字节(实际读到的字节数可 能比80少)并将读来的字节写入当前目录下的文件fout.txt 如果使用的是字节流,所以只能保证读取的是80个英文字符,如果中文则会出现问题
6、:编写一个程序,接收从键盘输入的数据,并把从键盘输入的内容写到input.txt文件中,如果输 入"quit",则程序结束。 默认文件是覆盖,可以修改FileOutputStream fos=new FileOutputStream(“fout.txt”, true); 使用字符流针对字符操作要方便的多
7、使用字符流实现文件的拷贝
8、编写一个程序实现如下功能,文件fin.txt是无行结构(无换行符)的包含中文字符的文本文件, 从fin中读取字符,写入文件fou.txt中,每40个字符一行(最后一行可能少于40个字)
9、:统计一个文件calcCharNum.txt中字母’A’和’a’出现的总次数
10、统计一个文件calcCharNum.txt中各个字母出现次数:A(8),B(16),C(10)…,a(12),b(10),c(3)…,括 号内代表字符出现次数; 扩展按照出现次数从小到达排序 使用OOP
11、编写一个程序,把指定目录下的所有的带.java文件都拷贝到另一个目录中,拷贝成功后,把后缀 名是.java的改成.txt
12、编写一个程序,其功能是将多个文本文件的内容合并到一个文本文件中
13、找到一个大于100k的文件,按照100k为单位,拆分成多个子文件,并且以编号作为文件名结束。 比如文件 eclipse.exe,大小是309k。拆分之后,成为eclipse.exe-0、eclipse.exe-1、eclipse.exe-2、 eclipse.exe-3
简答题
-
请描述异常的继承体系
-
请描述你对错误(Error)的理解
虚拟机的异常,一帮情况下无法避免
-
请描述你对异常(Expection的理解)
- 分为受检性异常和非受检性异常
- 受检性异常:无法避免(停电啦,断网啦,地震啦)
- 非受检性异常:一般由于程序逻辑问题导致;越早发现越好,
-
请描述你对运行时异常(RuntimeException)的理解
- 运行时异常。非受检性异常,由程序逻辑导致,早发现早解决
-
throw与throws的区别
- throw:方法内部抛出异常使用
- throes:在方法声明中,给调用者提醒一下我这可能会报一个错误,而且我解决不了,或者说我没解决
-
异常处理方式有几种,分别是什么?详细阐述每种方式对异常是如何处理的
- 向上抛出
- 捕获并进行对应的处理
-
请列举常见异常,并说明产生原因。
- 对象类型转换异常
- 数组或字符串超出索引
- 数学异常(除0操作)
- 空指针异常
- 引用类型zhuan’huan
课堂练习题
1、读取指定文件中的指定数量的字节数。
编写一个程序实现如下功能,从当前目录下的文件fin.txt中读取80个字节(实际读到的字节数可能比80少)并将读来的字节写入当前目录下的文件fout.txt
使用字符进行读入,但是每一次往后还是一个字节
package com.yang3;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Reader;
import java.io.Writer;
public class T05 {
public static void main(String[] args) throws FileNotFoundException, IOException {
ziJie();
}
public static void ziJie() throws FileNotFoundException, IOException {
try (InputStream in = new FileInputStream("D:\\桌面\\a.txt");
OutputStream out = new FileOutputStream("D:\\桌面\\c.txt")) {
for (int i = 0; i < 50; i++) {
int tmp = in.read();
if (tmp == -1) {
break;
}
out.write(tmp);
}
}
}
public static void ziFu() throws FileNotFoundException, IOException {
try (Reader in = new FileReader("D:\\桌面\\a.txt"); Writer out = new FileWriter("D:\\桌面\\b.txt")) {
for (int i = 0; i < 80; i++) {
int tmp = in.read();
if (tmp == -1) {
break;
}
out.write((char) tmp);
}
}
}
}
扩展小芝士
- 编码问题:全部读入,直接转字符串,然后输出
- System.out和System.err的混合使用输出执行顺序不能保证,要用就用一个
for (int i = 0; i < 10; i++) {
if (i % 2 == 0) {
System.err.println("偶数");
} else {
System.out.println("奇数");
}
}
- 使用native修饰的方法是本地方法,本地方法通过对等类的方法来实现
- unicode只是一个编码的规范,就像是java中的接口,他只是规定了应该怎么做,至于真正的字符用几个字节存储,那些字节存储那些数字,像UTF-8就是针对Unicode的一种可变长度字符编码。
- java中想实现
\
字符的替换则需要使用\\
来替代一个\
,在路径中的话需要使用\\\\
来替代一个文件层级