網路IO-IO操作的常用API
本地磁碟檔案操作之File
File類簡介
-
File類是Java中為檔案進行建立、刪除、重新命名、移動等操作而設計的一個類。它是屬於Java.io包下的類。
File類基本操作
-
- File(File parent,String child): 根據parent抽象路徑名和child路徑名字串建立一個新的File例項
-
- File(String pathname): 將指定路徑名轉化為抽象路徑名建立一個新的File例項
-
- File(String parent,String child):根據parent路徑名和child路徑名建立一個File 例項
-
- File(URI uri): 指定URI轉化為抽象路徑名
基於檔案的位元組輸入輸出流實戰
{
//根據使用者端輸入的路徑進行目錄的遍歷
public static void main(String[] args) throws IOException {
InputStreamReader reader =new InputStreamReader(System.in);
BufferedReader bufferedReader = new BufferedReader(reader);
try {
String path = bufferedReader.readLine();File file = new File(path);
if (file.isDirectory()&&file.exists()){
//去遍歷這個目錄下所有的子目錄
fileList(file);
}else{
System.out.println("檔案路徑輸入錯誤");
}
} catch (IOException e) {
e.printStackTrace();
}finally {
bufferedReader.close();reader.close();
}
}
private static void fileList(File filePath){
File[] files = filePath.listFiles();
if (files !=null){
for (int i =0;i <files.length;i++){
if (files[i].isFile()){
//輸出具體的檔名
System.out.println(files[i].getName());
}else{
//如果是一個目錄
fileList(files[i]);
}
}
}
}
}
深入淺出read方法
Read輸入
當讀取不到資料的時候read()返回值為-1
為了防止提高效能使用baye[]資料進行儲存資料,每次讀取資料長度為陣列長度,避免每次都進行互動,資料長度應該適當,長度越大佔用記憶體空間越大
public classReadDemo {
public staticvoidmain(String[] args) {
try{
FileInputStreamfileInputStream =newFileInputStream("F:/test.txt");
inti =0;
byte[] buffer =new byte[3];
//讀取指定目錄的位元組,如果read方法沒有輸入,會阻塞
while((i =fileInputStream.read(buffer)) != -1){
//fileOutputStream.write(i);
System.out.print(newString(buffer,i));
}
}catch(Exception e) {
e.printStackTrace();
}
}
}
基於記憶體的位元組輸入輸出流實戰
使用ByteArrayInputStream()方法進行操作
public classMemoryDemo {
staticStringstr="helloworld";
public static voidmain(String[] args){
//從記憶體種讀取資料
ByteArrayInputStreaminputStream =newByteArrayInputStream(str.getBytes());
//寫出到記憶體種
ByteArrayOutputStreamoutputStream =newByteArrayOutputStream();
inti =0;
while((i =inputStream.read()) != -1){
charc = (char)i;
outputStream.write(Character.toUpperCase(c));
}
System.out.println(outputStream.toString());
}
}
基於緩衝流的輸入輸出實戰
-
緩衝流:緩衝流是帶緩衝區的處理流,它會提供一個緩衝區,緩衝區的作用的主要 目的是:避免每次和硬碟打交道,能夠提高輸入/輸出的執行效率。分別為BufferedInputStream()與BufferedOutputStream()
public class BufferedDemo {
public static void main(String[] args) {
try(BufferedInputStream bufferedInputStream =new BufferedInputStream
(new FileInputStream("F:/test.txt"));
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream
(new FileOutputStream("F:/tes.txt"))) {
int len = 0;
byte[] bys = new byte[1024];
while ((len = bufferedInputStream.read(bys)) != -1){
System.out.println(new String(bys,len));
bufferedOutputStream.write(bys,len);
bufferedOutputStream.flush();
}
}catch (Exception e){
}
}
}
普通流的輸入輸出與緩衝流的輸入輸出執行速度比較
public class BudderedCopyDemo {
private static File fileSource =
new File("E:/Test001.zip");
private static File fileTarget =
new File("E:/Test001_cp.zip");
public void copyWithNormal(){
try(FileInputStream fileInputStream =
new FileInputStream(fileSource);
FileOutputStream fileOutputStream =
new FileOutputStream(fileTarget)) {
int i = 0;
byte[] bytes = new byte[1024];
while ( (i = fileInputStream.read(bytes)) != -1){
fileOutputStream.write(bytes);
}
} catch (Exception e) {
e.printStackTrace();
}
}
public void copyWithBuffered(){
try(FileInputStream fileInputStream =
new FileInputStream(fileSource);
FileOutputStream fileOutputStream =
new FileOutputStream(fileTarget);
BufferedInputStream bufferedInputStream =
new BufferedInputStream(fileInputStream);
BufferedOutputStream bufferedOutputStream =
new BufferedOutputStream(fileOutputStream)) {
int i = 0;
byte[] bytes = new byte[1024];
while ( (i = bufferedInputStream.read(bytes)) != -1){
bufferedOutputStream.write(bytes);
}
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
BudderedCopyDemo budderedCopyDemo =
new BudderedCopyDemo();
long stra = System.currentTimeMillis();
budderedCopyDemo.copyWithNormal();
long end =System.currentTimeMillis();
System.out.println("普通方式進行讀取:"+(end-stra));
stra = System.currentTimeMillis();
budderedCopyDemo.copyWithBuffered();
end =System.currentTimeMillis();
System.out.println("緩衝流方式進行讀取:"+(end-stra));
}
}
執行結果:
詳解Flush方法
public class FlushDemo {
public static void main(String[] args) throws Exception {
BufferedOutputStream bufferedOutputStream =
new BufferedOutputStream(new FileOutputStream("E:/liyao.txt"));
bufferedOutputStream.write("hello wrld".getBytes());
}
}
當前程式碼複製檔案,程式碼執行完成檔案並沒有資料寫入
public class FlushDemo {
public static void main(String[] args) throws Exception {
BufferedOutputStream bufferedOutputStream =
new BufferedOutputStream(new FileOutputStream("E:/liyao.txt"));
bufferedOutputStream.write("hello wrld".getBytes());
bufferedOutputStream.flush();
}
}
增加flush()方法,程式碼執行完成檔案資料寫入成功
因為快取區大小預設為8kb但是我們現在的檔案沒有達到8kb所有不會進行磁碟重新整理。flush()方法做了一個類似與刷盤的操作,如果使用 try/ catch相當於觸發了close()方法,close()也會觸發flush()進行一個刷盤操作
基於檔案的字元輸入輸出流實戰
public classByteReadDemo {
public staticvoidmain(String[] args) {
try(FileInputStreamfileInputStream =newFileInputStream("E:/liyao.txt")) {
intlen =0;
while((len =fileInputStream.read()) != -1){
System.out.print((char)len);
}
}catch(Exception e){
e.getStackTrace();
}
}
}
輸出
因為read()一次讀取一個位元組,而漢字一次4個位元組所以就會出現亂碼。解決辦法之一增加byte[]資料進行資料儲存讓它一次性提交完成。從而避免亂碼。注意:這裡的檔案格式為UTF-8
位元組流:
public classByteReadDemo {
public staticvoidmain(String[] args) {
try(FileInputStreamfileInputStream =newFileInputStream("E:/liyao.txt")) {
intlen =0;
byte[] by=new byte[1024];
while((len =fileInputStream.read(by)) != -1){
System.out.print(newString(by,len));
}
}catch(Exception e){
e.getStackTrace();
}
}
}
輸出
字元流:
public classReaderWriterDemo {
public staticvoidmain(String[] args) {
try(FileReaderfileReader =newFileReader("E:/liyao.txt")){
intlen =0;
char[] chars =new char[1024];
while((len =fileReader.read(chars))!= -1){
System.out.println(newString(chars,len));
}
}catch(Exception e){
e.getStackTrace();
}
}
}
輸出:
位元組流與字元流的轉換輸出
public classConvertDemo {
public staticvoidmain(String[] args) {
try(BufferedInputStreaminputStream =newBufferedInputStream(newFileInputStream("E:/liyao.txt")) ){
InputStreamReaderinputStreamReader =newInputStreamReader(inputStream,"UTF-8");
BufferedReaderbufferedReader =newBufferedReader(inputStreamReader);
System.out.println(bufferedReader.readLine());//讀取一行資料
String str =bufferedReader.readLine();
//字元轉換流
OutputStreamWriteroutputStreamWriter =newOutputStreamWriter(newFileOutputStream("E:/liyao_cp.txt"),"UTF-8");
BufferedWriterbufferedWriter =newBufferedWriter(outputStreamWriter);
bufferedWriter.write("1234");
bufferedWriter.flush();
}catch(Exception e){
}
}
}
序列化和反序列化
-
序列化:序列化是把物件的狀態資訊轉化為可儲存或傳輸的形式過程,也就是把對 象轉化為位元組序列的過程稱為物件的序列化
-
反序列化:反序列化是序列化的逆向過程,把位元組陣列反序列化為物件,把位元組序列 恢復為物件的過程成為物件的反序列化
序列化DEMO
建立user物件
public class User implements Serializable {
private String name;
private long age;
public User(String name,long age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public long getAge() {
return age;
}
public void setAge(long age) {
this.age = age;
}
@Override
public String toString() {
return "TestDemo{" +
"name=‘" + name + ‘\‘‘ +
",age=" + age +
‘}‘;
}
}
實現序列化與反序列化
public class ObjectDemo {
public static void main(String[] args) {
//ObjectInputStream
//實現物件序列化
User user = new User("Tom",18);//儲存到記憶體中
try(ObjectOutputStream objectOutputStream = new ObjectOutputStream
(new FileOutputStream("E:/user111"))){
objectOutputStream.writeObject(user);
}catch (Exception e){
e.printStackTrace();
}
//ObjectInputStream
//反序列化
try(ObjectInputStream objectInputStream = new ObjectInputStream
(new FileInputStream("E:/user111"));) {
user = (User) objectInputStream.readObject();
System.out.println(user);
}catch (Exception e){
}
}
}
深入分析IO的底層原理
IO流的整個體系與互動過程邏輯圖
Read()把資料從核心緩衝區複製到程序的使用者空間的緩衝區
Write()把程序的緩衝區複製到核心緩衝區在通過磁碟控制器寫入到本地磁碟
所有操作是跟緩衝區互動,緩衝區滿了在寫磁碟,寫入的資料到緩衝區沒有同步到磁碟。那麼當伺服器宕機的時候,緩衝區的資料就有可能會丟失
緩衝IO的優點:
它在一定程度分離了使用者空間與核心空間保護了系統本身的一個執行安全
它可以減少與磁碟的互動次數,從而提升效能
緩衝IO的缺點:
不能在應用程式直接與磁碟進行資料傳輸,需要進行多次資料拷貝帶來CUP的效能損耗,記憶體損耗