【知晓的丧day拯救计划】java基础学习笔记25 IO流

笔记来自
2019求知讲堂零基础Java入门编程视频教程 https://www.bilibili.com/video/av76235341

尚学堂 java300集

IO原理及流的分类

IO:input + output
流:数据流

IO流用来处理设备之间的数据传输。
Java程序中,对于数据的输入/输出操作,也是以流(Stream)的方式进行。
java.io包下提供了各种“流”类和接口,用以获取不同类型的数据,并通过标准的方法输入输出数据。

输入input:读取外部数据(磁盘、光盘等存储设备的数据)到程序(内存)中。
输出output:将程序(内存)数据输出到磁盘、光盘等存储设备中。

流的分类
按操作数据单位不同分为:字节流(8 bit),字符流(16 bit)
按数据流的流向不同分为:输入流、输出流
按数据流的功能不同分为:节点流、处理流

IO流的四大抽象基类

抽象基类字节流字符流
输入流InputStreamReader
输出流OutputStreamWriter

常用方法:

抽象类常用方法
InputStreamint read() 从输入流读取数据的下一个字节
void close() 关闭此输入流并释放与流相关的系统资源
OutputStreamvoid write(int b) 将指定的字节写入此输出流
void flush() 刷新此输出流并强制将内存中缓冲的输出字节被写出
void close() 关闭此输出流并释放与流相关的系统资源
Readerint read() 读一个字符
Writer append
void close() 关闭流并释放与流相关的系统资源
Writervoid write(String) 写一个字符串
Writer append(char c) 将指定字符添加到Witter对象
void flush() 刷新流
void close() 关闭流并释放与流相关的系统资源

一个处理流的标准步骤:
1.创建源
2.选择流
3.操作(读、写)
4.释放资源

一个简单例子便于理解:

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;

public class TestIOStream {
	public static void main(String[] args) {		
		//1.创建源
		File src = new File("src/io/abc.txt"); //文件内容abc
		//2.选择流
		try {
			InputStream is = new FileInputStream(src);
			//3.操作(读取)
			int data1 = is.read();  //读取第一个数据a
			int data2 = is.read();  //读取第一个数据b
			int data3 = is.read();  //读取第一个数据c
			int data4 = is.read();  //读取到文件末尾
			
			System.out.println((char)data1); //read()方法返回值是int,需要强转为char
			System.out.println((char)data2);
			System.out.println((char)data3);
			System.out.println(data4);       //读到文件末尾返回-1
			
			//4.释放资源
			is.close();
			
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

IO流体系

Java的IO流涉及40多个类,实际上都是由四个抽象基类派生的。由这4个类派生的子类名称都是以其父类名称作为后缀的。

分类字节输入流字节输出流字符输入流字符输出流
抽象基类InputStreamOutputStreamReaderWriter
访问文件FileInputStreamFileOutputStreamFileReaderFileWriter
访问数组ByteArrayInputStreamByteArray OutputStreamCharArrayReaderCharArrayWriter
访问管道PipedInputStreamPipedOutputStreamPipedReaderPipedWriter
访问字符串StringReaderStringWriter
缓冲流BufferedInputStreamBufferedOutputStreamBufferedReaderBufferedWriter
转换流InputStreamReaderOutputStreamWriter
数据流DataInputStreamDataOutputStream
对象流ObjectInputStreamObjectOutputStream
过滤流FilterInputStreamFilterOutputStreamFilterReaderFilterWriter
打印流PrintStreamPrintWriter
输入流PushbackInputStreamPushbackReader

节点流

节点流是直接和数据源交互的的流,包括文件流和数组流。

文件流

文件流是对硬盘上文件的操作,必须借助操作系统进行读写,使用完后要通知操作系统释放资源。

FileInputStream 文件字节输入流

通过字节的方式读取文件,适合读取所有类型的文件(图像、音视频等),如果是纯文本文件可以考虑使用FileReader。

构造方法

  • FileInputStream(File file)
    打开一个文件输入流,通过File对象来指定输入流的源文件
  • FileInputStream(String name)
    打开一个文件输入流,通过文件路径来指定输入流的源文件
  • FileInputStream(FileDescriptor fdObj)

常用方法

方法作用
int read()读取单个字节,返回该字节数据
int read(byte[] b)读取b.length个字节到缓存数组b中,返回的int是数组大小
int read(byte[] b, int off, int len)指定数据存放在b中的起始位置和长度
int available()返回此输入流中剩余的字节数
long skip(long n)跳过并丢弃输入流中n个字节的数据
void close()通知操作系统关闭文件输入流并释放相关系统资源
  • int read()
    读取单个字节,返回该字节数据

一段比较标准的使用read()读取文件的写法

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;

public class TestFileInputStream {	
	public static void main(String[] args) {
		//1.创建源。要读取的文件对象
		File src = new File("src/io/abc.txt");
		//因为finally语句块要使用对象is,所以声明部分提出到try语句外边
		InputStream is = null;
		try {
			//2.选择流(文件输入流)
			is = new FileInputStream(src);
			//3.操作。读取数据
			//temp用来暂时存放读出来的单个字节
			int temp;
			//当读出的不是-1(说明文件没到末尾),循环读取单个字节
			while((temp = is.read())!= -1) {
				//输出单个字节
				System.out.print((char)temp);
			}
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}finally {
			//4.释放资源,关闭流。无论是否出现异常,都需要关闭流,所以写在finally语句块中
			try {
				if(null!=is) {
					is.close();
				}				
			} catch (IOException e) {
				e.printStackTrace();
			}
		}		
	}
}
  • int read(byte[] b)
    读取b.length个字节到缓存数组b中,返回的int是数组大小(读完文件中最后一组数据后会再往后读一次,并返回-1)
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;

public class TestFileInputStream {
	
	public static void main(String[] args) {
		//1.创建源
		File src = new File("src/io/abc.txt");
		InputStream is = null;
		try {
			//2.选择流
			is = new FileInputStream(src);
			//3.操作(分段读取)
			//确定数组长度,每次读取的字节数。长度一般以K为单位
			//byte[] flush = new byte[1024*10]; 表示一次读取10k
			byte[] flush = new byte[5];  
			//len为数组的接收长度,剩余字节大于数组长度就是数组长度,剩余字节小于字节长度就是剩余字节数,读到文件结尾返回-1
			int len = -1; 
			//如果len不等于-1(说明文件没到末尾),循环读取
			while((len = is.read(flush))!=-1) {
				//为了避免读取最后一个数组时,读到数组结尾不是文件内容的部分,使用new String(byte[] b,int off,int len)
				String str = new String(flush, 0, len);
				System.out.print(str);
			}
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}finally {
			//4.释放资源
			try {
				if(null!=is) {
					is.close();
				}				
			} catch (IOException e) {
				e.printStackTrace();
			}
		}	
	}
}
  • int read(byte[] b, int off, int len)
    将读取的数据放到缓存数组b中的时候,只从数组b的第off个位置开始存放,放len个数据,返回b中存放数据的个数
File src = new File("src/io/abc.txt");
//文件内容:abcdefghigklmn
try (InputStream is3 = new FileInputStream("src/io/abc.txt")){
	byte[] flush = new byte[5];  
	is3.read(flush,2,2);
	System.out.println("*" + new String(flush) + "*"); // *  ab *
	is3.read(flush,1,3);
	System.out.println("*" + new String(flush) + "*"); // * cde *
	is3.read(flush,1,4);
	System.out.println("*" + new String(flush) + "*"); // * fghi*
	
	is3.read(flush,0,5);//此处相当于is3.read(flush)
	System.out.println("*" + new String(flush) + "*"); // *gklmn*
} catch (Exception e) {
	e.getStackTrace();
}
  • long skip(long n)
    跳过并丢弃输入流中n个字节的数据
File src = new File("src/io/abc.txt");
//文件内容:abcdefghigklmn
try (InputStream is2 = new FileInputStream("src/io/abc.txt")){
	byte[] flush = new byte[5];  
	int len = -1; 
	while((len = is2.read(flush))!=-1) {
		String str = new String(flush, 0, len);
		//每读取5个字节丢弃一个字节
		is2.skip(1);
		System.out.print(str);
	}
} catch (Exception e) {
	e.getStackTrace();
}
//运行结果:abcdeghigkmn
  • void close()
    通知操作系统释放资源
FileOutputStream

通过字节的方式写出或追加数据到文件,适合所有类型的文件(图像、音视频等),如果是纯文本文件可以考虑使用FileWriter。

构造方法

  • FileOutputStream(String name)
    创建一个文件输出流,写入由文件路径指定的目标文件
  • FileOutputStream(File file)
    创建一个文件输出流,写入由File对象指定的目标文件
  • FileOutputStream(String name, boolean apppeding)
    创建一个文件输出流,写入由文件路径指定的目标文件,并指定写入时是否为追加(true为追加,false为重写)
  • FileOutputStream(File file, boolean apppeding)
    创建一个文件输出流,写入由File对象指定的目标文件,并指定写入时是否为追加(true为追加,false为重写)
  • FileOutputStream(FileDescriptor fdObj)

常用方法

方法作用
void write(int b)将指定字节写入文件输出流
void write(byte[] b)将指定字节数组的b.length个字节写入文件输出流
void write(byte[] b, int off, int len)将指定字节数组b中,从偏移off个字节开始的len个字节写入文件输出流
void close()关闭此文件输出流并释放与此流关联的所有系统资源。
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;

public class TestFileOutputStream {
	public static void main(String[] args) {
		//1.创建源
		File src = new File("src/io/out.txt");
		//2.选择流
		OutputStream os = null;
		try {
			//追加方式写入
			os = new FileOutputStream(src,true);
			//3.操作(写出)
			//要写出的内容
			String msg = "hello exception";
			//编码 字符串-->字节
			byte[] datas = msg.getBytes();
			//write(byte[] b,int off,int len)方法写出字节数组
			os.write(datas, 0, datas.length);
			//刷新流,避免数据滞留在内存中,未写到文件
			os.flush();
						
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}finally {
			//4.释放资源
			try {
				if(null!=os) {
					os.close();
				}				
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
}
FileInputStream + FileOutputStream文件拷贝
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;

public class TestFileCopy {
	public static void main(String[] args) {
		copy("src/io/sw.jpg", "src/io/swcopy.jpg");
	}

	public static void copy(String srcPath, String destPath) {
		// 1.创建源
		File src = new File(srcPath);
		File dest = new File(destPath);

		// 2.选择流
		InputStream is = null;
		OutputStream os = null;
		try {
			is = new FileInputStream(src);
			os = new FileOutputStream(dest);
			// 3.操作(copy)
			byte[] flush = new byte[1024];
			int len = -1;
			while ((len = is.read(flush)) != -1) {
				os.write(flush, 0, len);
			}
			os.flush();

		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			// 4.释放资源(分别关闭,先打开的后关闭)
			try {
				if(null!=os) {
					os.close();
				}				
			} catch (IOException e) {
				e.printStackTrace();
			}
			try {
				if(null!=is) {
					is.close();
				}				
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
}

FileReader

FileReader和FileWriter只能用于纯文本文件,因为不同的字符集每个字符占的字节数不同,例如最常用的utf-8字符集中,英文占一个字节,中文占三个字节,这样中英文混合的文档解码起来非常容易因为字节数不同而导致乱码。
字符输入输出流可以解决这个问题,它直接以字符为单位进行传输。

构造方法

  • FileReader(File file)
    打开一个文件字符输入流,通过File对象来指定输入流的源文件
  • FileReader(String fileName)
    打开一个文件字符输入流,通过文件路径来指定输入流的源文件
  • FileReader(FileDescriptor fd)

常用方法

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;

public class TestFileReader {
	public static void main(String[] args) {
		//1.创建源
		File file = new File("src/io/abc.txt");
		//2.选择流
		Reader reader = null;
		try {
			reader = new FileReader(file);
			//3.操作(分段读取)
			char[] flush = new char[10];
			int len = -1;
			while((len = reader.read(flush))!=-1) {
				String str = new String(flush, 0, len);
				System.out.print(str);
			}					
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}finally {
			try {
				if(null!= reader) {
					reader.close();
				}				
			} catch (IOException e) {
				e.printStackTrace();
			}
		}		
	}
}

FileWriter

构造方法

  • FileWriter(File file)
  • FileWriter(String fileName)
  • FileWriter(File file, boolean append)
  • FileWriter(String fileName, boolean append)
  • FileWriter(FileDescriptor fd)

常用方法

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;

public class TestFileWriter {
	public static void main(String[] args) {
		// 1.创建源
		File dest = new File("src/io/dest.txt");
		// 2.选择流
		Writer writer = null;
		try {
			writer = new FileWriter(dest);
			// 3.操作()写出
			// 要写出的内容
			//写法一
			String msg = "KFC肯德基";
			char[] datas = msg.toCharArray();
			// write(byte[] b,int off,int len)方法写出字节数组
			writer.write(datas, 0, datas.length);
			// 刷新流,避免数据滞留在内存中,未写到文件
			writer.flush();
			
			//写法二
			writer.write(msg); //字符串本身就是字符数组,可以直接写入
			writer.flush();

			//写法三
			writer.append(msg).append("真好吃");
			writer.flush();
			
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			// 4.释放资源
			try {
				if(null!= writer) {
					writer.close();
				}				
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
}

字节数组流

字节数组流是对另一个内存区域(可能是电脑上的另一块内存,也可能是网络上的一块内存)上的文件数组的操作。Java是可以直接访问内存的,所以就不需要借助操作系统,释放资源也是由垃圾回收机制进行的。但是为了代码的统一,也可以加上close()方法,这个方法是空的。

任何数据(基本类型、引用类型)都可以转换成字节数组,字节数组是二进制的,这样可以方便数据在网络上的传输。但内存是有限的,所以不建议用字节数组流处理过大的数据。

ByteArrayInputStream

ByteArrayInputStream 包含一个内部缓冲区,其中包含从流中读取的字节

构造方法

  • ByteArrayInputStream(byte[] buf)
    打开一个字节数组输入流,读取数据的源文件是一个字节数组
  • ByteArrayInputStream(byte[] buf, int offset, int length)
    -打开一个字节数组输入流,读取数据的源文件是一个字节数组中,从偏移off个字节开始的长度为len的部分

常用方法

  • int read()
  • int read(byte[] b, int off, int len)
  • int available()
  • long skip(long n)

与文件字节输入流的区别

1.输入源:是一个字节数组,这个数组不要太大
2.释放资源:实际上不需要

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;

public class TestByteArrayInputStream {
	public static void main(String[] args) {
		//1.创建源:是字节数组,不要太大
		byte[] src = "today is a terrible day".getBytes();
		InputStream is = null;
		try {
			// 2.选择流
			is = new ByteArrayInputStream(src);
			// 3.操作(分段读取)
			byte[] flush = new byte[5];
			int len = -1;
			while ((len = is.read(flush)) != -1) {
				String str = new String(flush, 0, len);
				System.out.print(str);
			}
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			// 4.释放资源:实际不需要,为了代码风格统一可以加上
			try {
				if(null!= is) {
					is.close();
				}				
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
}
ByteArrayOutputStream

ByteArrayOutputStream字节数组输出流,数据被写入一个字节数组,缓冲区会在数据写入时自动增长
构造方法

  • ByteArrayOutputStream()
    创建一个字节数组输出流,不需要写输出流的目的地,系统会自动创建一个缓冲区
  • ByteArrayOutputStream(int size)
    创建一个字节数组输出流,并指定缓冲区大小

常用方法

方法作用
int size()返回当前缓冲区的大小。
void write(int b)将指定字节写入字节数组输出流
void write(byte[] b, int off, int len)将字节数组中的指定部分写入字节数组输出流
void writeTo(OutputStream out)将字节数组输出流写入到指定的输出流中
String toString()使用工程默认字符集将缓冲区的内容转换为字符串
String toString(String charsetName)使用指定字符集将缓冲区的内容转换为字符串
byte[] toByteArray()将缓冲区的内容写出到一个新的字节数组
void reset()重置缓冲区(理解为清空缓冲区中的数据)

与文件字节输入流的区别
1.不需要创建源,自动创建一个新的字节数组输出流
2.需要使用toByteArray()从字节数组输出流中获取数据
3.由于toByteArray()是ByteArrayOutputStream新增的方法,所以在声明时不能使用多态
4.释放资源:实际上不需要

import java.io.ByteArrayOutputStream;
import java.io.IOException;

public class TestByteArrayOutputStream {
	public static void main(String[] args) {
		// 1.创建源:不需要创建源,自动创建一个新的字节数组输出流
		byte[] dest = null;
		// 2.选择流(因为要使用ByteArrayOutputStream新增方法,所以不使用多态)
		ByteArrayOutputStream baos = null;
		try {
			baos = new ByteArrayOutputStream();
			// 3.操作
			// 要写出的内容
			String msg = "today is a terrible day";
			byte[] datas = msg.getBytes();
			//写出
			baos.write(datas, 0, datas.length);
			baos.flush();
			//获取数据
			dest = baos.toByteArray();
			System.out.println(new String(dest, 0, dest.length));			
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			// 4.释放资源
			try {
				if(null!= baos) {
					baos.close();
				}				
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
}
综合:对接流(文件字节流与字节数组流的转换)
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
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;

public class TestFileToByteArray {
	public static void main(String[] args) {
		// 图片文件到字节数组
		byte[] datas = fileToByteArray("src/io/sw.jpg");
		System.out.println(datas.length);
		// 字节数组到图片文件
		byteArrayToFile(datas, "src/io/sw-byte.jpg");
	}

	// 图片读取到字节数组
	// 1)图片到程序 FileInputStream
	// 2)程序到字节数组 ByteArrayOutputStream
	public static byte[] fileToByteArray(String filePath) {
		//1.创建源与目的地
		File src = new File(filePath);
		byte[] dest = null;
		// 2.选择流
		InputStream is = null;
		ByteArrayOutputStream baos = null;
		try {
			is = new FileInputStream(src);
			baos = new ByteArrayOutputStream();
			// 3.操作
			byte[] flush = new byte[1024 * 10];
			int len = -1;
			while ((len = is.read(flush)) != -1) {
				baos.write(flush, 0, len);
			}
			baos.flush();
			// 获取数据
			dest = baos.toByteArray();
			return dest;
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			// 4.释放资源
			if (null != is) {
				try {
					is.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
		return null;
	}

	// 字节数组写出到图片
	// 1)字节数组到程序 ByteArrayInputStream
	// 2)程序到图片 FileOutputStream
	public static void byteArrayToFile(byte[] src, String filePath) {
		// 1.创建源与目的地
		File dest = new File(filePath);
		// 2.选择流
		InputStream is = null;
		OutputStream os = null;
		try {
			is = new ByteArrayInputStream(src);
			os = new FileOutputStream(dest);
			// 3.操作
			byte[] flush = new byte[1024*10];
			int len = -1;
			while ((len = is.read(flush)) != -1) {
				os.write(flush, 0, len);				
			}
			os.flush();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			///4.释放资源
			if(null!=os) {
				try {
					os.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
}

处理流

处理流是在节点流基础上的,对节点流的包装,以提高性能。

缓冲流

缓冲流用于提高IO操作的性能。
在内存中有一块缓冲区,读写操作时,流会先存在缓冲区中,当缓冲区写满之后,才进行硬盘的读取,这样减少了读写硬盘的次数,提高性能。

BufferedInputStream

构造方法

  • BufferedInputStream(InputStream in)
    将指定输入流写入此缓冲输入流,缓冲区默认为8k
  • BufferedInputStream(InputStream in, int size)
    将指定输入流写入此缓冲输入流,并指定缓冲区大小

常用方法

  • int available()
  • void close()
  • int read()
  • long skip(long n)
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;

public class BufferInputStream {
	public static void main(String[] args) {
		//1.创建源
		File src = new File("src/io/abc.txt");
		//2.选择流
		InputStream is = null;	
		try {
			//处理流,直接包装到节点流外层
			is = new BufferedInputStream(new FileInputStream(src));
			//3.操作(分段读取)
			byte[] flush = new byte[5];  
			int len = -1; 
			while((len = is.read(flush))!=-1) {
				String str = new String(flush, 0, len);
				System.out.print(str);
			}
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}finally {
			//4.释放资源
			try {
				if(null!= is) {
					is.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}		
	}
}
BufferedOutputStream

构造方法

  • BufferedOutputStream(OutputStream out)
    创建新的缓冲输出流,将数据写入指定的基础输出流
  • BufferedOutputStream(OutputStream out, int size)
    创建新的缓冲输出流,将数据写入指定的基础输出流,同时指定缓冲区大小

常用方法

  • void write(int b)
  • void write(byte[] b, int off, int len)
  • void flush()
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;

public class TestBufferedOutputStream {
	public static void main(String[] args) {
		//1.创建源
		File src = new File("src/io/abc.txt");
		//2.选择流
		OutputStream os = null;
		try {
			os = new BufferedOutputStream(new FileOutputStream(src));
			//3.操作
			String msg = "hello exception";
			byte[] datas = msg.getBytes();
			os.write(datas, 0, datas.length);
			os.flush();
			
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}finally {
			//4.释放资源
			try {
				if(null!= os) {
					os.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
}
BufferedReader

构造方法

  • BufferedReader(Reader in)
  • BufferedReader(Reader in, int sz)

常用方法

  • long skip(long n)
    跳过字符
  • int read()
    读取一个字符
  • int read(char[] cbuf, int off, int len)
    读取字符数组中的指定部分
  • String readLine()
    读取一行字符(此方法为BufferedReader新增方法,要使用声明时不能使用多态)
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;

public class TestBufferedReader {
	public static void main(String[] args) {
		//1.创建源
		File file = new File("src/io/abc.txt");
		//2.选择流
		BufferedReader reader = null;
		try {
			reader = new BufferedReader(new FileReader(file));
			//3.操作(分段读取)
			String line = null;
			//readLine() BufferedReader新方法,逐行读取文本
			while((line = reader.readLine())!=null) {
				System.out.println(line);
			}			
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}finally {
			try {
				if(null!= reader) {
					reader.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}		
	}
}
BufferedWriter

构造方法

  • BufferedWriter(Writer out)
  • BufferedWriter(Writer out, int sz)

常用方法

  • void flush() 刷新流
  • void newLine() 写一个换行符
  • void write(int c) 写一个字符
  • void write(char[] cbuf, int off, int len) 写一个字符数组的一部分
  • void write(String s, int off, int len) 写一个字符串的一部分
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;

public class TestBufferedWriter {
	public static void main(String[] args) {
		// 1.创建源
		File dest = new File("src/io/dest.txt");
		// 2.选择流
		BufferedWriter writer = null;
		try {
			writer = new BufferedWriter(new FileWriter(dest));
			// 3.操作
			String msg = "KFC肯德基";
			writer.append(msg);
			//newLine() 添加一个换行符
			writer.newLine();
			writer.append("真好吃");
			writer.flush();			
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			// 4.释放资源
			try {
				if(null!= writer) {
					writer.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
}
用字符缓冲流实现文档拷贝
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

public class CopyTxt {
	public static void main(String[] args) {
		copy("src/io/abc.txt", "src/io/abc-copy.txt");
	}

	public static void copy(String srcPath, String destPath) {
		// 1.创建源
		File src = new File(srcPath);   //源
		File dest = new File(destPath); //目的

		// 2.选择流
		try(BufferedReader br = new BufferedReader(new FileReader(src));
				BufferedWriter bw = new BufferedWriter(new FileWriter(dest))) {
			// 3.操作(逐行读取)
			String line = null;		
			while ((line = br.readLine())!=null) {
				bw.write(line); //逐行写入
				bw.newLine();
			}
			bw.flush();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

转换流

转换流是字节流与字符流之间的桥梁,能将(纯文本的)字节流转换成字符流,并且为字节流指定字符集

InputStreamReader

由于将纯文本的字节流转直接解码成字符很可能会因为字节数不够或字符集不统一的原因造成乱码,所以需要通过转换流,将字节流按照指定的字符集转换成字符流。

构造方法

  • InputStreamReader(InputStream in) 默认使用当前工程所使用的的字符集。
  • InputStreamReader(InputStream in,String charsetName),使用指定字符集。

常用方法

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;

public class TestInputStreamReader {
	public static void main(String[] args) {		
		//指定字符集
		//操作网络流,下载百度首页源码
		try(BufferedReader reader = 
				// 因为已经转换成字符流,所以加上BufferedReader提高性能
				new BufferedReader(
						//将字节流转换成字符流
						new InputStreamReader(
								//一个简单的网络流,从指定网址获得源代码的字节流
								//由于获得的是字节流,且网页源码是纯文本,所以可以使用InputStreamReader将字节流转换成字符流
								//不指定字符集默认使用工程使用的字符集(本工程使用utf-8)
								//最好按照网页的编码字符集进行解码,百度使用utf-8
								new URL("http://www.baidu.com/").openStream(),"utf-8"));){
			String msg;	
			while((msg = reader.readLine())!=null) {
				System.out.println(msg);
			}			
		}catch (Exception e) {
			e.getStackTrace();
		}		
	}
}
OutputStreamWriter

构造方法

  • OutputStreamWriter​(OutputStream out)
  • OutputStreamWriter​(OutputStream out, String charsetName)

将获取的网页源码存为baidu.html
FileOutputStream --> OutputStreamWriter --> BufferedWriter

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileOutputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.URL;

public class TestOutputStreamWriter {
	public static void main(String[] args) {
		try(BufferedReader reader = 
				new BufferedReader(
						new InputStreamReader(
								new URL("http://www.baidu.com/").openStream(),"utf-8"));
			BufferedWriter writer =
				new BufferedWriter(
						new OutputStreamWriter(
								new FileOutputStream("src/io/baidu.html"), "utf-8"))){
			String msg;	
			while((msg = reader.readLine())!=null) {
				writer.write(msg);
				writer.newLine();				
			}
			writer.flush();
		}catch (Exception e) {
			e.getStackTrace();
		}
	}
}

System.in&System.out 循环输入输出

系统输入System.in和系统输出System.out都是纯文本的字节流,可以将他们转换成字符流方便处理(readLine()和newLine()),并加上缓冲流提高性能。

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;

public class TestInputStreamReader {
	public static void main(String[] args) {
		//操作System.in和system.out
		//处理字符流最好都加上Buffered以提高性能
		try(BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
				BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(System.out));){
			//实现循环获取键盘输入的内容并打印,碰到exit退出
			String msg = "";
			while (!msg.equals("exit")) {
				msg = reader.readLine();  //循环读取
				writer.write(msg);        //循环写出
				writer.newLine();         //换行
				writer.flush();           //强制刷新
			}			
		}catch (IOException e) {
			e.getStackTrace();
		}
	}
}	

数据流

DataInputStream & DataOutputStream

数据输出流可以将数据类型(基本数据类型和字符串类型)写入输出流,然后程序可以使用数据输入流来读取数据和对应的数据类型(先写入后读取,且读取的顺序和写入的顺序必须保持一致,否则会导致读取错误或程序报错)

构造方法

  • DataOutputStream(OutputStream out)
  • DataInputStream(InputStream in)

常用方法

  • 各种数据类型的read()和write()方法
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;

public class TestDataInputStream {	
	public static void main(String[] args) throws IOException {
		// 写出到字节数组
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		DataOutputStream dos = new DataOutputStream(baos);
		dos.writeUTF("数据流");
		dos.writeInt(123);
		dos.writeBoolean(true);
		dos.writeChar((int)'a');
		dos.flush();
		byte[] datas = baos.toByteArray();
		
		//从字节数组读取
		DataInputStream dis = new DataInputStream(new ByteArrayInputStream(datas));
		//读取顺序与写入顺序一致
		String str = dis.readUTF();
		int i = dis.readInt();
		boolean b = dis.readBoolean();
		char c = dis.readChar();
		System.out.println(str);
		System.out.println(i);
		System.out.println(b);
		System.out.println(c);		
	}
}

对象流

ObjectOutputStream&ObjectInputStream

对象流可以把一个对象转化成数据流,并进行读写。(先写入后读取,读取顺序与写入顺序必须一致)。
还要注意的是,并不是所有的对象都可以序列化,一个类必须实现serializable接口,其对象才能序列化。
ObjectOutputStream(序列化)将Java的基本数据类型或对象写入OutputStream,流文件可以实现对象的持久存储。如果对象的某个数据不想被序列化,可以使用修饰符transient。
ObjectInputStream (反序列化)可以读取(重构)基本数据类型和对象

构造方法

  • ObjectOutputStream(OutputStream out) 将对象的流写入指定的OutputStream
  • ObjectInputStream(InputStream in) 从指定的InputStream读取对象

常用方法

  • 各种数据类型的read()和write()方法
  • readObject()
  • writeObject()
  • transient 标记不需要序列化的数据
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

public class TestObjectStream {
	public static void main(String[] args) throws IOException, ClassNotFoundException {
		// 写出到字节数组(序列化)
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		ObjectOutputStream oos = new ObjectOutputStream(baos);
		oos.writeInt(123);
		oos.writeBoolean(true);
		oos.writeObject("字符串也是对象");
		Person p = new Person(2000,"知晓", 25);
		oos.writeObject(p);
		oos.flush();
		byte[] datas = baos.toByteArray();
		
		//从字节数组读取(反序列化)
		ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(datas));
		//读取顺序与写入顺序一致
		int i = ois.readInt();
		boolean b = ois.readBoolean();
		Object strObj = ois.readObject();
		Object personObj = ois.readObject();
		
		System.out.println(i);
		System.out.println(b);
		//对象数据还原
		if(strObj instanceof String) {
			String str = (String)strObj;
			System.out.println(str);
		}
		if(personObj instanceof Person) {
			Person person = (Person)personObj;
			System.out.println(person.getName()+ "   " + person.getAge());  //知晓 0 (age没有被序列化)

		}
		
//——————————————————————————————————————————————————————————————				
		// 写出到文件(序列化)
		ObjectOutputStream oos2 = 
				new ObjectOutputStream(
						new BufferedOutputStream(
								new FileOutputStream("src/io/personlist.txt")));
		
		Person p1 = new Person(2001,"张三", 26);
		Person p2 = new Person(2002,"李四", 30);
		oos2.writeObject(p1);
		oos2.writeObject(p2);
		oos2.flush();
		oos2.close();
		
		//从文件读取(反序列化)
		ObjectInputStream ois2 = 
				new ObjectInputStream(
						new BufferedInputStream(new FileInputStream("src/io/personlist.txt")));
		//读取顺序与写入顺序一致
		Object personObj1 = ois2.readObject();
		Object personObj2 = ois2.readObject();		
		//对象数据还原
		if(personObj1 instanceof Person) {
			Person person = (Person)personObj1;
			System.out.println(person.getId() + "--" + person.getName());  //知晓 0 (age没有被序列化)
		}
		if(personObj2 instanceof Person) {
			Person person = (Person)personObj2;
			System.out.println(person.getId() + "--" + person.getName());  //知晓 0 (age没有被序列化)
		}		
		ois2.close();		
	}
}

//对象要转换成流,必须实现序列化接口Serializable
class Person implements Serializable{
	private int id;
	private String name;
	private transient int age; //transient 关键字代表该数据不需要序列化
		
	public Person() {
		super();
	}	
	public Person(int id, String name, int age) {
		super();
		this.id = id;
		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;
	}
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}	
}

打印流

PrintStream

PrintStream 方便打印各种类型的数据

构造方法

  • PrintStream(File file) 打印到指定文件

  • PrintStream(File file,String csn) 打印到指定文件,并指定字符集

  • PrintStream(String fileName) 打印到指定文件

  • PrintStream(String fileName, String csn) 打印到指定文件,并指定字符集

  • PrintStream(OutputStream out) 转换成节点流

  • PrintStream(OutputStream out, boolean autoFlush) 转换成节点流,是否自动刷新

  • PrintStream(OutputStream out, boolean autoFlush, String encoding) 转换成节点流,是否自动刷新,并指定字符集

常用方法

  • print() 打印各种数据类型的数据,不换行
  • println() 打印各种数据类型的数据,默认结尾换行
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileDescriptor;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintStream;
import java.io.UnsupportedEncodingException;

public class TestPrintStream {
	public static void main(String[] args) throws FileNotFoundException, UnsupportedEncodingException {
		//打印流 打印到控制台
		PrintStream ps = System.out;
		ps.println("控制台");
		
		//打印流,输出到文件字节流,自动刷新
		ps = new PrintStream(new BufferedOutputStream(new FileOutputStream("src/io/print.txt")),true);
		ps.println("通过文件输出流打印到文件");
		ps.close();
		
		ps = new PrintStream(new BufferedOutputStream(new FileOutputStream("src/io/print.txt")));
		ps.println("通过文件输出流打印到文件");
		//输出到流没有自动刷新时,需要手动刷新
		ps.flush();
		ps.close();
		
		//打印流 输出到文件
		ps = new PrintStream(new File("src/io/print.txt"),"utf-8");
		ps.println("通过File对象直接打印到文件");
		ps = new PrintStream("src/io/print.txt","utf-8");
		ps.println("通过文件名直接打印到文件");
	}
}
  • 重定向输出端

我们平常输出用的System.out.print(),默认是输出到控制台的。可以使用System.setOut(PrintStream out),修改输出的位置。

//重定向输出端
System.setOut(ps);
System.out.println("123"); //此时直接打印到文件中

修改之后还可以将其修改回控制台

//重定向回控制台
System.setOut(new PrintStream(new BufferedOutputStream(new FileOutputStream(FileDescriptor.out)),true));
System.out.println("123");  //此时打印到控制台
PrintWriter

PrintWriter与 PrintStream类似,只处理文本数据

构造方法
PrintWriter(File file)
PrintWriter(File file, String csn)
PrintWriter(String fileName)
PrintWriter(String fileName, String csn)
PrintWriter(OutputStream out)
PrintWriter(OutputStream out, boolean autoFlush)
PrintWriter(Writer out)
PrintWriter(Writer out, boolean autoFlush)

其他流

RandomAccessFile

RandomAccessFile 是随机存取文件流 ,同时支持读和写,可以随机访问文件。
要注意的是,这里的随机不是真正的随机,而是指可以从指定的位置开始读写,不同于其他流的读取和写入都是从头开始或从末尾追加,所以可以实现文件的分割处理。

构造方法
RandomAccessFile(File file, String mode)
RandomAccessFile(String fileName, String mode)
mode用来指定是读还是写(“r”读,“rw”读写)

常用方法

  • 流相关的read()、write()方法
  • seek(long pos) 设置指针偏移,从文件的开头开始计算,确定下一次读取或写入的位置

使用seek的例子

import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;

public class TestRandomAccessFile {
	public static void main(String[] args) throws IOException {

		// 从指定位置开始,读到文件结束
		RandomAccessFile raf = new RandomAccessFile(new File("src/io/abc.txt"), "r");
		// 随机读取
		raf.seek(2); //从第3个字节开始读取
		byte[] flush = new byte[1024];
		int len = -1;
		//循环读取到文件结束
		while ((len = raf.read(flush)) != -1) {
			System.out.println(new String(flush, 0, len));
		}
		raf.close();

//————————————————————————————————————————————————————————————————		
		// 从指定位置开始,读取指定大小的内容
		RandomAccessFile raf2 = new RandomAccessFile(new File("src/io/abc.txt"), "r");
		int beginPos = 2; // 指定起始位置
		int actualSize = 12; // 指定需要的长度
		// 随机读取
		raf2.seek(beginPos); //从指定起点开始读取
		byte[] flush2 = new byte[10];
		int len2 = -1;
		while ((len2 = raf2.read(flush2)) != -1) {
			//如果剩余需要读取的数据大于当前缓存数组的大小
			if (actualSize > len2) {
				//那么这个缓存数组中的数据全部读取
				System.out.print(new String(flush2, 0, len2));
				//剩余需要读取的数据减去已读的部分,即数组长度
				actualSize -= len2;
				
			//如果剩余需要读取的数据小于当前缓存数组的大小
			} else {
				//那么只需要读取剩余这部分的长度,并结束循环
				System.out.print(new String(flush2, 0, actualSize));
				break;
			}
		}
		raf2.close();

		// 从指定位置开始写入
		RandomAccessFile raf3 = new RandomAccessFile(new File("src/io/abc.txt"), "rw");		
		raf3.seek(5); //从第6个字节开始写入,并覆盖原有数据
		raf3.writeBytes("xxx");
		raf3.close();
	}
}
SequenceInputStream

SequenceInputStream 可以将多个流合并起来,方便操作

构造方法

  • SequenceInputStream(InputStream s1,InputStream s2)
    将两个InputStream按先后顺序合并成一个SequenceInputStream对象
  • SequenceInputStream(Enumeration<? extend InputStream> e)
    将多个InputStream(或者其子类)按顺序合并成一个SequenceInputStream对象,一般使用Vector集合来存放要合并的流,然后使用Vector的getElems()方法获得Enumeration<E>。
使用面向对象的思想封装分割合并文件的方法

此代码只考虑了面向对象的封装以及合并分割的大致流程,没有过多考虑异常处理。

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.RandomAccessFile;
import java.io.SequenceInputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Vector;

public class SplitFile {
	private File src; // 被分割的源文件
	private String destDir; // 分割后文件的存储目录
	private List<String> destPaths; // 所以分割后文件的存储路径
	private int blockSize; // 每块的大小
	private int size; // 分割后的块数

	public SplitFile(String srcPsth, String destDir, int blockSize) {
		super();
		this.src = new File(srcPsth);
		this.destDir = destDir;
		this.blockSize = blockSize;
		this.destPaths = new ArrayList<String>();
		// 初始化
		init();
	}

	// 初始化
	private void init() {
		// 计算块数
		long len = this.src.length();
		//相除之后向上取整
		this.size = (int) Math.ceil(len * 1.0 / this.blockSize);
		// 存放子文件的路径
		for (int i = 0; i < this.size; i++) {
			this.destPaths.add(this.destDir + "/" + i + "-" + this.src.getName());
		}
	}

	public void split() throws IOException {
		long len = src.length();  //被分割的文件长度
		int beginPos = 0;  //分割的起始位置
		//实际分割的长度 :剩余长度大于指定分割长度就是指定的长度,剩余长度小于指定分割长度就是文件剩余的长度
		int actualSize = (int) (blockSize > len ? len : blockSize);   

		for (int i = 0; i < size; i++) {
			beginPos = i * blockSize;
			//如果是最后一块,只写出剩余部分即可
			if (i == size - 1) {
				actualSize = (int) len;
			//如果不是最后一块,写出指定分块长度
			} else {
				actualSize = blockSize;
				len -= blockSize;
			}
			//分割细节
			splitDetail(i,beginPos, actualSize);
		}
	}

	// 从指定位置开始,读取指定大小的内容
	private void splitDetail(int i,int beginPos, int actualSize) throws IOException {
		//读
		RandomAccessFile raf = new RandomAccessFile(this.src, "r");
		//写
		RandomAccessFile raf2 = new RandomAccessFile(this.destPaths.get(i), "rw");
		// 随机读取
		raf.seek(beginPos);
		byte[] flush = new byte[10];
		int len = -1;
		while ((len = raf.read(flush)) != -1) {
			if (actualSize > len) {
				raf2.write(flush, 0, len);
				actualSize -= len;
			} else {
				raf2.write(flush, 0, actualSize);
				break;
			}
		}
		raf2.close();
		raf.close();
	}
	
	//将多个文件依次读取并追加写出
	public void merge(String dest) throws IOException {
		//输出流
		OutputStream os = new BufferedOutputStream(new FileOutputStream(dest,true));
		//输入流
		for (String srcPath:destPaths) {
			InputStream is = new BufferedInputStream(new FileInputStream(srcPath));
			byte[] flush = new byte[1024];
			int len = -1;
			while((len = is.read(flush))!=-1) {
				os.write(flush, 0, len);
			}
			os.flush();
			is.close();	
		}
		os.close();		
	}
	
	//使用SequenceInputStream合并流之后再写出
	public void merge2(String dest) throws IOException {
		//输出流
		OutputStream os = new BufferedOutputStream(new FileOutputStream(dest,true));
		//存放多个输入流的集合
		Vector<InputStream> vi = new Vector<InputStream>();
		//输入流
		SequenceInputStream sis = null;	
		//将多个输入流加到集合中
		for (String srcPath:destPaths) {
			vi.add(new BufferedInputStream(new FileInputStream(srcPath)));			
		}
		//合并集合中的流
		sis = new SequenceInputStream(vi.elements());
		//写入
		byte[] flush = new byte[1024];
		int len = -1;
		while((len = sis.read(flush))!=-1) {
			os.write(flush, 0, len);
		}
		os.flush();
		sis.close();
		os.close();		
	}
	
	public static void main(String[] args) throws IOException {
		SplitFile splitFile = new SplitFile("src/io/sw.jpg", "src/io/dest",1024*10);
		splitFile.split();
		splitFile.merge("src/io/dest/sw2.jpg");
		splitFile.merge2("src/io/dest/sw3.jpg");
	}
}

相关接口

Closable 关闭流接口

实现此接口,才可以使用简化的try-catch-resource,自动释放资源

Flushable 刷新流接口

实现此接口,自动进行刷新

Serializable 序列化接口

实现此接口的对象才可以被序列化,才能转换成对象流传输存储。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
基于C++&OPENCV 的全景图像拼接 C++是一种广泛使用的编程语言,它是由Bjarne Stroustrup于1979年在新泽西州美利山贝尔实验室开始设计开发的。C++是C语言的扩展,旨在提供更强大的编程能力,包括面向对象编程和泛型编程的支持。C++支持数据封装、继承和多态等面向对象编程的特性和泛型编程的模板,以及丰富的标准库,提供了大量的数据结构和算法,极大地提高了开发效率。12 C++是一种静态类型的、编译式的、通用的、大小写敏感的编程语言,它综合了高级语言和低级语言的特点。C++的语法与C语言非常相似,但增加了许多面向对象编程的特性,如类、对象、封装、继承和多态等。这使得C++既保持了C语言的低级特性,如直接访问硬件的能力,又提供了高级语言的特性,如数据封装和代码重用。13 C++的应用领域非常广泛,包括但不限于教育、系统开发、游戏开发、嵌入式系统、工业和商业应用、科研和高性能计算等领域。在教育领域,C++因其结构化和面向对象的特性,常被选为计算机科学和工程专业的入门编程语言。在系统开发领域,C++因其高效性和灵活性,经常被作为开发语言。游戏开发领域中,C++由于其高效性和广泛应用,在开发高性能游戏和游戏引擎中扮演着重要角色。在嵌入式系统领域,C++的高效和灵活性使其成为理想选择。此外,C++还广泛应用于桌面应用、Web浏览器、操作系统、编译器、媒体应用程序、数据库引擎、医疗工程和机器人等领域。16 学习C++的关键是理解其核心概念和编程风格,而不是过于深入技术细节。C++支持多种编程风格,每种风格都能有效地保证运行时间效率和空间效率。因此,无论是初学者还是经验丰富的程序员,都可以通过C++来设计和实现新系统或维护旧系统。3

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值