IO流
File类的使用
/* File类的使用
*
* 1.File类的一个对象,代表一个文件或一个文件目录(俗称:文件夹)
* 2.File类声明在java.io包下
* 3.File类中涉及到关于文件或文件目录的创建、删除、重命名、修改时间、文件大小等方法,
* 并未涉及到写入或读取文件内容的操作。如果需要读取或写入文件内容,必须使用IO流来完成。
* 4.后续File类的对象常会作为参数传递到流的构造器中,指明读取或写入的“终点”。
*/
public class File {
//如何创建File类的实例
//public File(String pathname)
//public File(String parent,String child)
//以parent为父路径,child为子路径创建File对象。
//public File(File parent,String child)
//根据一个父File对象和子文件路径创建File对象
//相对路径:相较于某个路径下,指明的路径。
//绝对路径:包含盘符在内的文件或文件目录的路径
@Test
public void test1(){
java.io.File file = new java.io.File("hello.text");//相对于当面meodule
}
/* public String getAbsolutePath():获取绝对路径
public String getPath() :获取路径
public String getName() :获取名称
public String getParent():获取上层文件目录路径。若无,返回null
public long length() :获取文件长度(即:字节数)。不能获取目录的长度。
public long lastModified() :获取最后一次的修改时间,毫秒值
如下两个方法适用于文件目录
public String[] list() :获取指定目录下的所有文件或者文件目录的名称数组
public File[] listFiles() :获取指定目录下的所有文件或者文件目录的File数组
*/
@Test
public void test2(){
}
//File类的重命名功能
// public boolean renameTo(File dest):把文件重命名为指定的文件路径
//比如:file1.renameTo(file2)为例:
// 要想保证返回true,需要file1在硬盘中是存在的,且file2不能在硬盘中存在
/* File类的判断功能
public boolean isDirectory():判断是否是文件目录
public boolean isFile() :判断是否是文件
public boolean exists() :判断是否存在
public boolean canRead() :判断是否可读
public boolean canWrite() :判断是否可写
public boolean isHidden() :判断是否隐藏
File类的创建功能
public boolean createNewFile() :创建文件。若文件存在,则不创建,返回false
public boolean mkdir() :创建文件目录。如果此文件目录存在,就不创建了。
如果此文件目录的上层目录不存在,也不创建。
public boolean mkdirs() :创建文件目录。如果上层文件目录不存在,一并创建
File类的删除功能
public boolean delete():删除文件或者文件夹
* */
}
复习
-
如何遍历Map的key集,value集,key-value集,使用上泛型
Map<String,Integer> map = new HashMap<>(); map.put(); ... //遍历key Set<String> keySet = map.keySet(); for(String key : keySet){ System.out.println(key); } //遍历values Collection<Integer> values = map.values(); Iterator<Tnteger> iterator = values.iterator(); while(iterator.hasNext()){ System.out.println(iterator.next()); } //遍历key-value Set<Map.Entry<String,Integer>> entrySet = map.entrySet(); Iterator<Map.Entry<String,Integer>> iterator = entrySet.iterator(); while(iterator.hasNext()){ Map.Entry<String,Integer> entry = iterator.next(); String key = entry.getKey(); Integer values = entry.getValues(); System.out.println(key + "----------" + values); }
-
写出使用Iterator和增强for循环遍历List的代码,使用上泛型
-
提供一个方法,用于遍历获取HashMap<String,String>中所有的value,并存放在List中返回,考虑撒谎给你集合中泛型的使用。
public List<String> getValueList(HashMap<String,String> map){ ArrayList<String> valueList = new ArrayList<>(); Collection<String> values = map.values(); for(String value : values){ valuesList.add(values); } return valuesList; }
-
创建一个与a.txt文件同目录下的另外一个文件b.txt
File file1 = new File("d:\\a\\a.txt"); File file2 = new File(file.getParent(),"b.txt");
-
Map接口中的常用方法有哪些
put (K k,V v);//增 V remove(K k);//删 put (K k,V v);//改 V get(K k);//查 int size();//长度
IO流
- I/O是Input/Output的缩写, I/O技术是非常实用的技术,用于处理设备之间的数据传输。如读/写文件,网络通讯等。
(抽象基类) | 字节流 | 字符流 |
---|---|---|
输入流 | InputStream | Reader |
输出流 | OutputStream | Writer |
/* 一、流的分类
* 1.操作数据单位:字节流、字符流
* 2.数据的流向:输入流、输入流
* 3.流的角色:字节流、处理流
*
* 二、流的体系结构
* 抽象基类 节点流(或文件流) 缓冲流(处理流的一种)
* InputStream FileInputStream BufferedInputStream
* OutputStream FileOutputStream BufferedOutputStream
* Reader FileReader BufferedReader
* Writer FileWriter BufferedWriter
*/
public class FileReaderWriterTest {
public static void main(String[] args) {
File file = new File("hello.txt");//相较于当前工程下
System.out.println(file.getAbsoluteFile());
File file1= new File("day13\\hello.txt");//正确操作
System.out.println(file1.getAbsoluteFile());
}
//将day13下的hello.txt文件内容读入程序中,并输出到控制台
/*
* 说明点:
* 1.read()的理解:返回读入的一个字符。如果达到文件末尾,返回-1
* 2.异常的处理:为了保证流资源一定可以执行关闭操作。需要使用try-catch-finally处理
* 3.读入的文件一定要存在,否则就会报FileNotFoundException*/
@Test
public void testFileReader() {
//1.实例化file文件
FileReader reader = null;
try {
File file = new File("D:\\Java\\Thread\\src\\day13\\hello.txt");//相较于当前Module
//2.提供具体的流
reader = new FileReader(file);
//3.数据的读入
//read():返回读入的一个字符,如果达到文件末尾,返回-1
int data = reader.read();
while (data != -1){
System.out.print((char)data);
data = reader.read();
}
} catch (IOException e) {
e.printStackTrace();
}
//4.流的关闭操作
try {
if (reader != null)
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
//对read()操作升级:使用read的重载方法
@Test
public void test2() {
FileReader fileReader = null;
try {
File file = new File("D:\\Java\\Thread\\src\\day13\\hello.txt");
fileReader = new FileReader(file);
//读入的操作
//read(char[] cbuf):返回每次读入cbuf数组中的字符的个数。如果达到文件末尾,返回-1
char[] cbuf = new char[5];
int len;
while ((len = fileReader.read(cbuf)) != -1){
//方式一:错误写法
// for (int i=0; i<cbuf.length;i++){
// System.out.print(cbuf[i]);
// }
//方式一正确写法
// for (int i=0; i<len;i++){
// System.out.print(cbuf[i]);
// }
//方式二错误写法
// String s = new String(cbuf);
// System.out.println(s);
//方式二正确写法
String ss = new String(cbuf, 0, len);
System.out.print(ss);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (fileReader != null)
fileReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/*从内从中写出数据到硬盘的文件里
*
* 说明:
* 1.输入操作,对应的File可以不存在
* 如果不存在,在输入的过程中,会自动创建此文件
* 如果存在:
* 如果流使用的构造器是:FileWriter(file,false) / FileWriter(file):对原有文件覆盖
* 如果流使用的构造器是:FileWriter(file,true):不会对原有文件覆盖,而是在原有文件基础上追加内容
* */
@Test
public void testWriter() throws IOException {
//1.提供File类的对象,指明写出到的文件
File file = new File("D:\\Java\\Thread\\src\\day13\\hello1.txt");
//2.提供FileWriter的对象,用于数据的写入
FileWriter writer = new FileWriter(file);
//3.写出的操作
writer.write("i hava a dream");
//4.流资源的关闭
writer.close();
}
//实现文本文件的复制
@Test
public void test3() throws IOException {
FileReader reader = null;
FileWriter writer = null;
try {
//1.创建File类的对象,指明读入和写出的文件
File file = new File("D:\\Java\\Thread\\src\\day13\\hello.txt");
File file1 = new File("D:\\Java\\Thread\\src\\day13\\hello1.txt");
//2.创建输入流和输出流的对象
reader = new FileReader(file);
writer = new FileWriter(file1);
//3.数据的读入和写出操作
char[] cbuf = new char[5];
int len;
while ((len = reader.read(cbuf)) != -1){
//每次写出len个字符
writer.write(cbuf,0,len);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
//4.关闭流资源
try {
if (reader != null)
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
if (writer != null)
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
缓冲流
/* 缓冲流的使用
*
* 1.缓冲流:
* BufferedInputStream
* BufferedOutputStream
* BufferedReader
* BufferedWriter
*
*
* 2.作用:提供流的读取、写入的速度
* 提高读写速度的原因:内部提供了一个缓冲区
*
* 3.处理流:就是“套接”在已有的流的基础上。
*
* 4.总结:抽象基类 节点流(或文件流) 缓冲流(处理流的一种)
* * InputStream FileInputStream(read(byte[] buffer)) BufferedInputStream(read(byte[] buffer))
* * OutputStream FileOutputStream(write(byte[] buffer,0,len))BufferedOutputStream(write(byte[] buffer,0,len))
* * Reader FileReader(read(char[] cbuf)) BufferedReader(read(char[] cbuf))
* * Writer FileWriter(write(char[] cbuf,0,len) BufferedWriter(write(char[] cbuf,0,len)
*/
public class BufferedTest {
/*
* 实现非文本文件的复制
*
* */
@Test
public void test1() {
BufferedInputStream bis = null;
BufferedOutputStream bos = null;
try {
//1.造文件
File srcfile = new File("C:\\Users\\Lenovo\\Desktop\\01.jpg");
File destfile = new File("C:\\Users\\Lenovo\\Desktop\\02.jpg");
//2.造流
//2.1造节点流
FileInputStream inputStream = new FileInputStream((srcfile));
FileOutputStream outputStream = new FileOutputStream((destfile));
//2.2造缓冲流
bis = new BufferedInputStream(inputStream);
bos = new BufferedOutputStream(outputStream);
//3.复制的细节:读取、写入
byte[] buffer = new byte[1024];
int len;
while ((len = bis.read(buffer)) != -1){
bos.write(buffer,0,len);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
//4.资源关闭:先关外面再关里面,但是如果你关闭了外面的,自动里面的就会关闭,所以只用close缓冲流
if (bis != null)
try {
bis.close();
} catch (IOException e) {
e.printStackTrace();
}
if (bis != null)
try {
bos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
//复制的方法
public void copy(String srcPath,String destPath){
BufferedInputStream bis = null;
BufferedOutputStream bos = null;
try {
//1.造文件
File srcfile = new File(srcPath);
File destfile = new File(destPath);
//2.造流
//2.1造节点流
FileInputStream inputStream = new FileInputStream((srcfile));
FileOutputStream outputStream = new FileOutputStream((destfile));
//2.2造缓冲流
bis = new BufferedInputStream(inputStream);
bos = new BufferedOutputStream(outputStream);
//3.复制的细节:读取、写入
byte[] buffer = new byte[1024];
int len;
while ((len = bis.read(buffer)) != -1){
bos.write(buffer,0,len);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
//4.资源关闭:先关外面再关里面,但是如果你关闭了外面的,自动里面的就会关闭,所以只用close缓冲流
if (bis != null)
try {
bis.close();
} catch (IOException e) {
e.printStackTrace();
}
if (bis != null)
try {
bos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
@Test
public void copytesr(){
long start = System.currentTimeMillis();
String srcPath = "C:\\Users\\Lenovo\\Desktop\\01.jpg";
String destPath = "C:\\Users\\Lenovo\\Desktop\\02.jpg";
copy(srcPath,destPath);
long end = System.currentTimeMillis();
System.out.println("复制操作花费的时间为:" + (end - start));
}
}
/*
* 使用BufferedReader和BufferedWriter实现文本文件的复制
*
*
* */
@Test
public void ReaderWritertest() {
BufferedReader br = null;
BufferedWriter bw = null;
try {
br = new BufferedReader(new FileReader(new File("D:\\Java\\Thread\\src\\day13\\dbcp.txt")));
bw = new BufferedWriter(new FileWriter(new File("D:\\Java\\Thread\\src\\day13\\dbcp1.txt")));
//读写操作
//方式一:使用char[]数组
char[] buffer = new char[1024];
int len;
while ((len = br.read(buffer)) != -1){
bw.write(buffer,0,len);
//方式二:使用String
String data;
while ((data = br.readLine())!= null){
//方法一:
//bw.write(data + "\n");//data中不包括换行符
//方法二:
bw.write(data);//data中不包括换行符
bw.newLine();
}
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (br != null) br.close();
if (bw != null) bw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
练习
-
文件的加密
-
public class PicTest { //图片的加密 @Test public void test1(){ FileInputStream fis = null; FileOutputStream fos = null; try { fis = new FileInputStream("C:\\Users\\Lenovo\\Desktop\\01.jpg"); fos = new FileOutputStream("C:\\Users\\Lenovo\\Desktop\\02.jpg"); byte[] buffer = new byte[20]; int len; while ((len = fis.read(buffer)) != -1){ for (int i = 0; i <len ; i++) { buffer[i] = (byte) (buffer[i] ^ 5); } fos.write(buffer,0,len); } } catch (IOException e) { e.printStackTrace(); } try { if (fis != null){ fis.close(); } } catch (IOException e) { e.printStackTrace(); } try { if (fos != null){ fos.close(); } } catch (IOException e) { e.printStackTrace(); } } //图片的解密 @Test public void test2(){ FileInputStream fis = null; FileOutputStream fos = null; try { fis = new FileInputStream("C:\\Users\\Lenovo\\Desktop\\02.jpg"); fos = new FileOutputStream("C:\\Users\\Lenovo\\Desktop\\03.jpg"); byte[] buffer = new byte[20]; int len; while ((len = fis.read(buffer)) != -1){ for (int i = 0; i <len ; i++) { buffer[i] = (byte) (buffer[i] ^ 5); } fos.write(buffer,0,len); } } catch (IOException e) { e.printStackTrace(); } try { if (fis != null){ fis.close(); } } catch (IOException e) { e.printStackTrace(); } try { if (fos != null){ fos.close(); } } catch (IOException e) { e.printStackTrace(); } } }
-
获取文本上每个字符出现的次数
转换流
/*
* 1.转换流:
* InputStreamReader:将InputStream转换为Reader(字节输入转换为字符输入)
* OutputStreamWriter:将Writer转换为OutputStream(字符输出转换为字节输出)
* 属于字符流
* 2.作用:提供字节流和字符流之间的转换
* 3.解码:字节、字节数组 ----》字符数组、字符串
* 编码:字符数组、字符串 ----》字节、字节数组
* 4.字符集
* 常见的编码表
* ASCII:美国标准信息交换码。
* 用一个字节的7位可以表示。
* ISO8859-1:拉丁码表。欧洲码表
* 用一个字节的8位表示。
* GB2312:中国的中文编码表。最多两个字节编码所有字符
* GBK:中国的中文编码表升级,融合了更多的中文文字符号。最多两个字节编码
* Unicode:国际标准码,融合了目前人类使用的所有字符。为每个字符分配唯一的
* 字符码。所有的文字都用两个字节来表示。
* UTF-8:变长的编码方式,可用1-4个字节来表示一个字符。
*
*/
public class InputStreamReaderTest {
@Test
public void test1() throws IOException {
FileInputStream fis = new FileInputStream("D:\\Java\\Thread\\src\\day13\\dbcp.txt");
InputStreamReader isr = new InputStreamReader(fis,"UTF-8");
char[] cbuf = new char[20];
int len;
while ((len = isr.read(cbuf)) != -1){
String s = new String(cbuf, 0, len);
System.out.print(s);
}
isr.close();
}
}
对象流
/* 对象流的使用
* 1.ObjectInputStream 和ObjectOutputStream
* 2.作用: 用于存储和读取基本数据类型数据或对象的处理流。它的强大之处就是可
* 以把Java中的对象写入到数据源中,也能把对象从数据源中还原回来。
* 3.要想一个java对象是可序列化的,需要满足相应的要求,见Person类
*/
public class ObjectInputOutputStreamTest {
/*
* 序列化过程:将内存中的java对象保存到磁盘中或通过网络传输出去
* 使用ObjectOutputStream实现
* */
@Test
public void test1(){
ObjectOutputStream oos = null;
try {
oos = new ObjectOutputStream(new FileOutputStream("object.dat"));
oos.writeObject(new String("我爱天安门"));
oos.flush();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (oos != null){
try {
oos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/*
* 反序列化:将磁盘文件中的对象还原为内存中的一个java对象
* 使用ObjectInputStream
* */
@Test
public void test2(){
ObjectInputStream obj = null;
try {
obj = new ObjectInputStream(new FileInputStream("object.dat"));
Object o = obj.readObject();
String str = (String) o;
System.out.println(str);
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} finally {
if (obj != null){
try {
obj.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
/* Person类需要满足如下的要求,方可序列化
*
* 1.需要实现接口:Serializable
* 2.需要当前类提供一个全局常量:serialVersionUID
* 3.除了当前Person类需要实现Serializable接口之外,还必须保证其内部所有属性也必须可序列化。
* (默认情况下,基本数据类型可系列化)
*/
public class Person implements Serializable {
public static final long serialVersionUID = 446464L;
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
随机存取文件流
/* RandomAccessFile的使用
* 1.RandomAccessFile直接继承于java.lang.Object类,实现了DataInput和DataOutput接口
* 2.RandomAccessFile既可以作为一个输入流,又可以作为一个输出流
* 3.如果RandomAccessFile作为输出流时,写出到的文件如果不存在,则在执行过程中自动创建
* 如果写出的文件存在,则会从文件内容的开头依次进行覆盖
*
*/
public class RandomAccessFileTest {
@Test
public void test1(){
RandomAccessFile raf1 = null;
RandomAccessFile raf2 = null;
try {
raf1 = new RandomAccessFile(new File("object.dat"), "r");
raf2 = new RandomAccessFile(new File("object1.dat"), "rw");
byte[] buffer = new byte[1024];
int len;
while ((len = raf1.read(buffer)) != -1){
raf2.write(buffer,0,len);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (raf1 != null){
try {
raf1.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (raf2 != null){
try {
raf2.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
@Test
public void test2(){
RandomAccessFile raf1 = null;
try {
raf1 = new RandomAccessFile("hello.txt", "rw");
raf1.write("xyz".getBytes());
} catch (IOException e) {
e.printStackTrace();
} finally {
if (raf1 != null){
try {
raf1.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
/* 4.可以通过相关的操作,可以进行插入操作
*/
/*
* 使用RandomAccessFile实现数据的插入效果
* */
@Test
public void test4(){
RandomAccessFile raf1 = null;
try {
raf1 = new RandomAccessFile("hello.txt", "rw");
raf1.seek(3);//将指针调到角标为3的位置
//保存指针3后面的所有数据到StringBuilder中
StringBuilder b = new StringBuilder((int) new File("hello.txt").length());
byte[] buffer = new byte[20];
int len;
while ((len = raf1.read(buffer)) != -1){
b.append(new String(buffer,0,len));
}
//调回指针,写入“xyz”
raf1.seek(3);
raf1.write("xyz".getBytes());
//现在的指针在“z”的后面,将StringBuilder中的数据写入到文件中
raf1.write(b.toString().getBytes());
} catch (IOException e) {
e.printStackTrace();
} finally {
if (raf1 != null){
try {
raf1.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}