java複習_進階
title: java複習_進階
tags:
- java
categories: - java
abbrlink: 47946
date: 2020-08-10 21:48:00
Java複習
本文主要進行java的複習與進階,複習部分參考java基礎,這裡只包含一些常用的API,進階部分預計包含javaBean,反射,泛型,註解,集合,IO
API
math.API
BigDecimal
public class LearnString_A { public static void main(String[] args) { BigDec big_data = new BigDec(); System.out.println(big_data.do_func()); } } class BigDec { public double do_func(){ BigDecimal a = new BigDecimal("2.0008"); BigDecimal b = new BigDecimal("1.00009"); BigDecimal res = a.subtract(b); //result.setScale(1,BigDecimal.ROUND_HALF_UP);//四捨五入 return res.doubleValue(); } }
util.API
Scanner
Scanner輸入與hasNext緩衝區輸入判斷
toCharArray進行字串分割與Character的字元判斷
public void CharSplit(){ Scanner scanner = new Scanner(System.in); if (scanner.hasNext()){ String input_data = scanner.next(); for (char c: input_data.toCharArray()){ // System.out.println(c); if (Character.getType(c)==Character.OTHER_LETTER){ System.out.println("chinese"); }else if (Character.isDigit(c)){ System.out.println(String.format("%-8d",Integer.parseInt(String.valueOf(c)))); }else if(Character.isLetter(c)){ System.out.println(String.format("%-8s", "letter")); }else { System.out.println(String.format("%-10s", "other character")); } } scanner.close(); }
String
String不可變
StringBuilder
可變物件,預分配緩衝區,向StringBuilder新增字元時,不會建立新的臨時物件
StingBuilder支援鏈式操作,使用append進行拼接,每個函式return this -> getValue()
StringJoiner
可以指定開頭和結尾,類似於python的join
public String StrConcat() { String[] names = {"Bob", "Alice", "Smith"}; StringJoiner origin_str = new StringJoiner(", ","Hello","!~~"); for (String name:names){ origin_str.add(name); } return origin_str.toString(); }
javaBean
BeanInfo
public class BeanLearn {
public static void main(String[] args) throws Exception {
BeanInfo info = Introspector.getBeanInfo(Person.class);
for(PropertyDescriptor pd:info.getPropertyDescriptors()){
System.out.println(pd.getName());
System.out.println(pd.getReadMethod());
System.out.println(pd.getWriteMethod());
}
}
}
classpath和jar
classpath
JVM環境變數,用於解決類依賴(後續有maven來解決此種依賴)
java -classpath .;system_path
java -cp ,;system_path
原則上不支援設定classpath,只有在單獨需求執行某個java檔案和其依賴時再使用
jar
由於jar包實際上就是zip包,可以直接打壓縮,字尾名zip改為jar就可以建立一個jar包
關於具體的jar包的格式,只需要注意,bin目錄不能作為第一級別目錄,打包jar包可以使用IDEA實現
java -jar hello.jar
執行jar包
內部類
內部類擁有外部類的訪問許可權,且可以變相實現多重繼承
public class OuterClass {
private String name;
private int age;
class InnerClass {
public InnerClass() {
name = "Mr.Wu";
age = 25;
}
}
}
反射,主界,泛型集合與IO
反射
訪問欄位
- Field getField(name):根據欄位名獲取某個public的field(包括父類)
- Field getDeclaredField(name):根據欄位名獲取當前類的某個field(不包括父類)
- Field[] getFields():獲取所有public的field(包括父類)
- Field[] getDeclaredFields():獲取當前類的所有field(不包括父類)
一個Field
物件包含了一個欄位的所有資訊:
getName()
:返回欄位名稱,例如,"name"
;getType()
:返回欄位型別,也是一個Class
例項,例如,String.class
;getModifiers()
:返回欄位的修飾符,它是一個int
,不同的bit表示不同的含義。
public static void main(String[] args) throws NoSuchFieldException {
Class<Student> stdClass = Student.class;
System.out.println(stdClass.getField("name"));
System.out.println(stdClass.getField("score"));
System.out.println(stdClass.getDeclaredField("grade"));
System.out.println(Arrays.toString(stdClass.getFields()));
}
class Person{
public String name;
}
class Student extends Person{
public int score;
private int grade;
}
//類物件+類屬性物件 -> 類屬性物件繫結例項 -> 得到值
Class<Student> stdClass = Student.class;
Object stu1 = new Student();
Field fie = stdClass.getField("name");
fie.setAccessible(true);
Object value = fie.get(stu1);
System.out.println(value);
fie.set(stu1,123);
System.out.println(fie.get(stu1));
此外,setAccessible(true)
可能會失敗。如果JVM執行期存在SecurityManager
,那麼它會根據規則進行檢查,有可能阻止setAccessible(true)
。例如,某個SecurityManager
可能不允許對java
和javax
開頭的package
的類呼叫setAccessible(true)
,這樣可以保證JVM核心庫的安全
訪問方法
Method getMethod(name, Class...)
:獲取某個public
的Method
(包括父類)Method getDeclaredMethod(name, Class...)
:獲取當前類的某個Method
(不包括父類)Method[] getMethods()
:獲取所有public
的Method
(包括父類)Method[] getDeclaredMethods()
:獲取當前類的所有Method
(不包括父類)
一個Method
物件包含一個方法的所有資訊:
getName()
:返回方法名稱,例如:"getScore"
;getReturnType()
:返回方法返回值型別,也是一個Class例項,例如:String.class
;getParameterTypes()
:返回方法的引數型別,是一個Class陣列,例如:{String.class, int.class}
;getModifiers()
:返回方法的修飾符,它是一個int
,不同的bit表示不同的含義。
public static void main(String[] args) throws Exception {
Class<Student> stdClass = Student.class;
// 獲取public方法getScore,引數為String:
System.out.println(Arrays.toString(stdClass.getMethod("getScore", String.class).getParameterTypes()));
// 獲取繼承的public方法getName,無引數:
System.out.println(stdClass.getMethod("getName").getReturnType());
// 獲取private方法getGrade,引數為int:
System.out.println(stdClass.getDeclaredMethod("getGrade", int.class));
}
//通過反射呼叫方法 方法物件+類物件 -> 方法物件繫結例項 -> 得到結果
Class<Student> stdClass = Student.class;
Object stu = new Student();
Method method = stdClass.getMethod("getScore", String.class);
Method.setAccessible(true)
// 靜態方法時使用null來代替stu物件(因為靜態方法無法new獲取,直接通過method即可繫結)
char[] res = (char[]) method.invoke(stu,"test");
System.out.println(res.getClass());
//
class Student extends Person {
public int getScore(String type) {
return 99;
}
private int getGrade(int year) {
return 1;
}
}
class Person {
public String getName() {
return "Person";
}
}
注:仍然遵循多型原則
呼叫構造方法
注意:只能呼叫無參構造方法
Person p = Person.class.newInstance();
getConstructor(Class...)
:獲取某個public
的Constructor
;getDeclaredConstructor(Class...)
:獲取某個Constructor
;getConstructors()
:獲取所有public
的Constructor
;getDeclaredConstructors()
:獲取所有Constructor
。
Constructor<Student> cons1 = Student.class.getConstructor(String.class, String.class);
Student stu = (Student)cons1.newInstance("2233","213");
System.out.println(stu.getGrade());
class Student extends Person {
private final String score;
private final String grade;
public Student(String score, String grade) {
super();
this.score = score;
this.grade = grade;
}
public String getScore() {
return score;
}
public String getGrade() {
return grade;
}
}
獲取父類物件
Class<? super Student> n = stdClass.getSuperclass();
System.out.println(n);//class Person
System.out.println(n.getSuperclass());//class java.lang.Object
// 獲取介面,只返回當前類的,無父類實現的介面
Class s = Integer.class;
Class[] is = s.getInterfaces();
如果是兩個Class
例項,要判斷一個向上轉型是否成立,可以呼叫isAssignableFrom()
:
Integer.class.isAssignableFrom(Number.class); // false,因為Number不能賦值給Integer
Java註解
元註解
最常用的元註解是@Target
。使用@Target
可以定義Annotation
能夠被應用於原始碼的哪些位置:
- 類或介面:
ElementType.TYPE
; - 欄位:
ElementType.FIELD
; - 方法:
ElementType.METHOD
; - 構造方法:
ElementType.CONSTRUCTOR
; - 方法引數:
ElementType.PARAMETER
。
另一個重要的元註解@Retention
定義了Annotation
的生命週期:
- 僅編譯期:
RetentionPolicy.SOURCE
; - 僅class檔案:
RetentionPolicy.CLASS
; - 執行期:
RetentionPolicy.RUNTIME
。
使用@Repeatable
這個元註解可以定義Annotation
是否可重複。
使用@Inherited
定義子類是否可繼承父類定義的Annotation
。@Inherited
僅針對@Target(ElementType.TYPE)
型別的annotation
有效,並且僅針對class
的繼承,對interface
的繼承無效:
處理註解
因為註解定義後也是一種class
,所有的註解都繼承自java.lang.annotation.Annotation
,因此,讀取註解,需要使用反射API。
Java提供的使用反射API讀取Annotation
的方法包括:
判斷某個註解是否存在於Class
、Field
、Method
或Constructor
:
Class.isAnnotationPresent(Class)
Field.isAnnotationPresent(Class)
Method.isAnnotationPresent(Class)
Constructor.isAnnotationPresent(Class)
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Range {
int min() default 0;
int max() default 255;
}
// javaBean
public class Person {
@Range(min=1, max=20)
public String name;
@Range(max=10)
public String city;
}
// 自定義檢查
void check(Person person) throws IllegalArgumentException, ReflectiveOperationException {
// 遍歷所有Field:
for (Field field : person.getClass().getFields()) {
// 獲取Field定義的@Range:
Range range = field.getAnnotation(Range.class);
// 如果@Range存在:
if (range != null) {
// 獲取Field的值:
Object value = field.get(person);
// 如果值是String:
if (value instanceof String) {
String s = (String) value;
// 判斷值是否滿足@Range的min/max:
if (s.length() < range.min() || s.length() > range.max()) {
throw new IllegalArgumentException("Invalid field: " + field.getName());
}
}
}
}
}
Java泛型
泛型定義與使用 :略
泛型的坑
由於泛型在編譯時進行擦拭,即將T -> Object 所以理論上對Object進行的操作都不能直接對泛型使用
- Object無法對基本型別(int)進行繼承或操作
- 理論上沒有必要通過反射獲取Object(無法獲取泛型型別)
- 理論上不能對Object進行例項化
- 不能進行泛型的覆寫override(泛型呼叫時方法名不能為內建方法)
- 可以繼承泛型類
public class TObject {
public static void main(String[] args) {
// Pair<int>pair = new Pair<>(1,2) wrong 泛型無法定義基本型別<Object>
Pair<Integer>pair = new Pair<>(1,2);
// 無法通過反射獲取到物件的泛型
System.out.println(pair.getClass());
System.out.println(Pair.class);
// 無法判斷帶泛型的例項類
System.out.println(pair instanceof Pair<Integer>);//exception
// 通過反射來獲取父類的泛型的型別
// 注意,Type-> Class + ParameterizedType + GenericArrayType + WildcardType
InPair ip = new InPair(1,2);
Class<InPair> inPairClass = InPair.class;
// 獲取父類的Type物件,這裡多做一遍的目的是為了防止沒有父類(即不是繼承類的情況)
Type t = inPairClass.getGenericSuperclass();
if (t instanceof ParameterizedType){
// 向下轉型為ParameterizedType
ParameterizedType pt = (ParameterizedType) t;
// 獲取到每個引數的Type物件(泛型可以有多個,如Map)
Type[] types = pt.getActualTypeArguments();
Type firstType = types[0];
// 向下轉型為Class,這裡可以不用轉型直接輸出
Class<?> typeClass = (Class<?>) firstType;
System.out.println(typeClass);
System.out.println(Arrays.toString(types));
}
// 簡便方式
Type[] types = ((ParameterizedType) t).getActualTypeArguments();
System.out.println(Arrays.toString(types));
}
}
class Pair<T> {
private T first;
private T last;
public Pair() {
}
public Pair(T first, T last) {
this.first = first;
this.last = last;
}
public T getFirst() {
return first;
}
public T getLast() {
return last;
}
// wrong 不能對泛型進行例項化
public void defineTObject(){
this.first = new T();
}
}
class InPair extends Pair<Integer>{
public InPair() {
super();
}
public InPair(Integer first, Integer last) {
super(first, last);
}
}
集合
Iterable
public class userCollection {
public static void main(String[] args) {
UseIterate user_define_iterate = new UseIterate();
Integer[] array = {1,2,3,4};
List<Integer> user_list = Arrays.asList(array);
user_define_iterate.getUser_list(user_list);
}
}
class UseIterate {
public static boolean isNull(List<?> p) {
return p.isEmpty() || !(p instanceof ArrayList);
}
public <T> void getUser_list(List<? super T> user_list) {
if (isNull(user_list)) {
/*for (Object ll : user_list) {
System.out.println(ll);
}*/
for(Iterator it_value =user_list.listIterator();it_value.hasNext();){
System.out.println(it_value.next());
}
}
else {
System.out.println("null");
}
}
}
- Collection頂層藉口,定義集合的約定
- List也是頂層藉口,繼承了Collection介面,也是ArrayList LinkedList等的父類
- Set Queue 也繼承了Collection介面,用法見下方
- Map為key,value儲存的物件
ArrayList
ArrayList是實現了List介面的動態擴容陣列,完全代替vector,除了其不是執行緒安全的這一點
執行緒安全的List Collections.synchronizedList-> List list = Collections.synchronizedList(new ArrayList(....))
public<T> void setSyn_safe_list(List<T> syn_safe_list) {
this.syn_safe_list = Collections.synchronizedList(new ArrayList<>(syn_safe_list));
}
編寫equals來進行contains判斷
- 自反性(Reflexive):對於非
null
的x
來說,x.equals(x)
必須返回true
; - 對稱性(Symmetric):對於非
null
的x
和y
來說,如果x.equals(y)
為true
,則y.equals(x)
也必須為true
; - 傳遞性(Transitive):對於非
null
的x
、y
和z
來說,如果x.equals(y)
為true
,y.equals(z)
也為true
,那麼x.equals(z)
也必須為true
; - 一致性(Consistent):對於非
null
的x
和y
來說,只要x
和y
狀態不變,則x.equals(y)
總是一致地返回true
或者false
; - 對
null
的比較:即x.equals(null)
永遠返回false
。
規則
- 先確定例項“相等”的邏輯,即哪些欄位相等,就認為例項相等;
- 用
instanceof
判斷傳入的待比較的Object
是不是當前型別,如果是,繼續比較,否則,返回false
; - 對引用型別用
Objects.equals()
比較,對基本型別直接用==
比較
public boolean equals(Object o) {
if (o instanceof Person) {
Person p = (Person) o;
return Objects.equals(this.firstName, p.firstName) && Objects.equals(this.lastName, p.lastName) && this.age == p.age;
}
return false;
}
Vector
Vector是一個執行緒安全的容器,對內部的每個方法都簡單粗暴的上鎖,因此,訪問效率遠遠低於ArrayList
其擴容為一倍擴容,而ArrayList為0.5倍擴容
Stack
注意到Deque
介面實際上擴充套件自Queue
Queue | Deque | |
---|---|---|
新增元素到隊尾 | add(E e) / offer(E e) | addLast(E e) / offerLast(E e) |
取隊首元素並刪除 | E remove() / E poll() | E removeFirst() / E pollFirst() |
取隊首元素但不刪除 | E element() / E peek() | E getFirst() / E peekFirst() |
新增元素到隊首 | 無 | addFirst(E e) / offerFirst(E e) |
取隊尾元素並刪除 | 無 | E removeLast() / E pollLast() |
取隊尾元素但不刪除 | 無 | E getLast() / E peekLast() |
注意,Stack均有列表和陣列兩種形式
IO流
轉換流 : InputStreamReader OutputStreamWriter
列印流:PrintStream PrintWriter
資料流:DataInputStream DataOutputStream
物件流:ObjectinputStream ObjectOutputStream
隨機存取檔案流:RandomAccessFile
File類
- 訪問檔名稱
getName();getPath();getAbsolutePath();getAbsoluteFile();getParent();renameTo(File newName)
- 檔案檢測
exists();canWrite();canRead();isFile();isDirectory();lastModify()時間戳;Length()位元組數
- 檔案操作
createNewFile();delete();mkDir();list();listFiles();
package com.learn.maven_wjh;
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
public class IO_file {
public static void main(String[] args) {
File f = new File("D:\\Node.js\\新建資料夾\\新建文字文件.txt");
// 可以獲取檔名或資料夾名稱
System.out.println(f.getName());
System.out.println(f.getPath() + ", " + f.getAbsolutePath());
// 注意,只能識別到工程目錄
File f1 = new File("src\\com\\learn");
System.out.println(f1.getAbsolutePath());
// createFile();
// createDirection();
File newFiles = new File(f.getParent());
}
public static void createFile() {
File oldFile = new File("E:\\IDEA_CODE\\src\\com\\learn\\maven_wjh\\file_test.txt");
// 如果檔案不存在
if (!oldFile.exists()) {
try {
boolean new_judge = oldFile.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
if(oldFile.exists()){
System.out.println(oldFile.lastModified());
boolean delete_judge = oldFile.delete();
System.out.println(delete_judge);
}
}
public static void createDirection(){
File direction = new File("src\\com\\learn\\java_final");
File absolute_dir = new File(direction.getAbsolutePath());
boolean create_judge = absolute_dir.mkdirs();
// File parent_dir = new File(direction.getParent());
// System.out.println(Arrays.toString(parent_dir.list()));
File parent_file = new File(direction.getParent());
System.out.println(Arrays.toString(parent_file.listFiles()));
}
public static void walkFile(File file){
if (file.isFile()){
System.out.println(file.getAbsolutePath());
}else {
System.out.println(file.getAbsolutePath()+"is direction");
File[] files = file.listFiles();
if(files!=null&&files.length>0){
for (File file1 : files) {
walkFile(file1);
}
}
}
}
}
Stream
- 輸入流:位元組(8bit)InputStream 字元(16bit)Reader
- 輸出流:位元組(8bit)OutputStream 字元(16bbit)Writer
package com.learn.java_final;
import com.sun.org.apache.xml.internal.resolver.readers.ExtendedXMLCatalogReader;
import java.io.ByteArrayInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.Arrays;
// 注意一般使用InputSteam作為超類,FileInputStream作為子類進行檔案讀寫,利用StringBuffer將read讀取到的數字陣列轉為字串進行拼接
public class tt_stream {
public static void main(String[] args) throws Exception {
String content;
// try (InputStream inputStream = new FileInputStream("D:\\Node.js\\新建資料夾\\新建文字文件.txt");) {
// content = readAsString(inputStream);
// }
// System.out.println(content);
out_read();
}
public static String readAsString(InputStream inputStream) throws Exception {
int n;
StringBuilder stringBuffer = new StringBuilder();
while ((n = inputStream.read()) != -1) {
stringBuffer.append((char) n);
}
return stringBuffer.toString();
}
public static void out_read() throws Exception {
// byte[] buffer = new byte[100];
byte[] bytes = {10, 4, 10, 30};
try (InputStream input = new ByteArrayInputStream(bytes)){
int n;
while ((n=input.read())!=-1){
System.out.print((char) n);
}
}
}
}
OutputStream
public static void writeSome() throws Exception {
try (OutputStream outputStream = new FileOutputStream("readme.txt")) {
// outputStream只能接受byte
outputStream.write("hello".getBytes(StandardCharsets.UTF_8));
// outputStream.flush() 將緩衝區的資料刷寫到檔案裡
}
}
注意,對輸入輸出流進行filter時,所有的型別均向上轉型為InputStream,是為了控制子類爆炸的情況出現
也可以自定義FilterInputStream
public class learnStream {
public static void main(String[] args) throws Exception {
byte[] data = "hello.world".getBytes(StandardCharsets.UTF_8);
try(CountInputStream inputStream = new CountInputStream(new ByteArrayInputStream(data))){
int n;
while ((n=inputStream.read())!=-1){
System.out.println((char) n);
}
System.out.println(inputStream.getBytesRead());
}
}
}
class CountInputStream extends FilterInputStream {
private int count = 0;
protected CountInputStream(InputStream in) {
super(in);
}
public int getBytesRead() {
return this.count;
}
public int read() throws IOException {
int n = in.read();
if (n != -1) {
this.count++;
}
return n;
}
public int read(byte[] b, int off, int len) throws IOException {
int n = in.read(b, off, len);
this.count += n;
return n;
}
}
位元組流
注意:無對應檔案時會報錯,寫入檔案會全覆蓋
public class copyFile {
public static void main(String[] args) throws FileNotFoundException {
String content = testFileReader("xx");
System.out.println(content);
testFileWriter(content,"readme.txt");
}
public static String testFileReader(String inPath){
StringBuilder stringBuilder = new StringBuilder();
try(FileReader fr = new FileReader(inPath);){
// 臨時儲存資料的字元陣列
char[] c = new char[1000];
int len = 0;
while ((len=fr.read(c))!=-1){
stringBuilder.append(new String(c, 0, len));
}
} catch (IOException e) {
e.printStackTrace();
}
return stringBuilder.toString();
}
public static void testFileWriter(String text,String outPath){
try {
FileWriter fw = new FileWriter(outPath);
fw.write(text);
fw.flush();
fw.close();
}catch (Exception e){
e.printStackTrace();;
}
}
public static void transferFile(String inPath,String outPath){
try{
FileReader fileReader = new FileReader(inPath);
FileWriter fileWriter = new FileWriter(outPath);
char[] chars = new char[100];
int len = 0;
while ((len = fileReader.read(c))!=-1){
fileWriter.write(c,0,len);
}
fileWriter.flush();
fileWriter.close();
fileReader.close();
}catch (Exception e){
e.printStackTrace();
}
}
}
緩衝流
FileInputStream,FileOutPutStream,FileReader,FileWriter
操作較慢,收到磁碟的制約
因此出現了對應的BufferedInputStream,BufferedOutputStream,BufferedReader,BufferedWriter
public class learnBufferFile {
public static void main(String[] args) {
try {
// testBufferedInputStream();
// testBufferedOutputStream();
copyFile();
} catch (Exception e) {
e.printStackTrace();
}
}
// 注意緩衝區大小,太小可能會出現亂碼
public static void testBufferedInputStream() throws Exception {
InputStream in = new FileInputStream("D:\\\\Node.js\\\\新建資料夾\\\\新建文字文件.txt");
BufferedInputStream br = new BufferedInputStream(in);
byte[] bytes = new byte[100];
int len = 0;
StringBuilder stringBuilder = new StringBuilder();
while ((len = br.read(bytes)) != -1) {
stringBuilder.append(new String(bytes, 0, len));
}
System.out.println(stringBuilder.toString());
// 先開後關,棧型操作
br.close();
in.close();
}
public static void testBufferedOutputStream() throws IOException {
OutputStream out = new FileOutputStream("readme1.txt");
BufferedOutputStream bo = new BufferedOutputStream(out);
String s = "hello world";
bo.write(s.getBytes());
bo.flush();
bo.close();
out.close();
}
// 緩衝字元流來複制檔案,注意緩衝區大小,太小可能會出現重複
public static void copyFile() throws IOException {
BufferedReader br = new BufferedReader(new FileReader("D:\\\\Node.js\\\\新建資料夾\\\\新建文字文件.txt"));
BufferedWriter bw = new BufferedWriter(new FileWriter("readme1.txt"));
char[] c = new char[20];
int len = 0;
StringBuffer stringBuffer = new StringBuffer();
while ((len = br.read(c))!=-1){
stringBuffer.append(c);
}
bw.write(stringBuffer.toString());
bw.flush();
bw.close();
br.close();
}
}
轉換流
InputStreamReader in = new InputStreamReader(new FileInputStream("xx"),"GBK");
OutStreamWriter os = new OutputStreamWriter(new FileOutputStream("xx"),"GBK");
通過轉換流與BufferedReader與PrintWriter進行讀寫
public class LearnFile {
private static final File f = new File("." + File.separator + "testFile.txt");
private static final Scanner SCANNER = new Scanner(System.in);
public static void main(String[] args) throws IOException {
File target_file = createFile();
System.out.println("write first");
line_write(target_file);
System.out.println("then read");
line_read(target_file);
}
public static File createFile() throws IOException {
if (f.isFile()) {
System.out.println("file already exist,and to delete it");
} else {
System.out.println(f.createNewFile());
}
return f;
}
public static void line_read(File file1) {
try (InputStream inputStream = new FileInputStream(file1);
InputStreamReader inputStreamReader = new InputStreamReader(inputStream,StandardCharsets.UTF_8);
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
) {
String line = null;
while ((line = bufferedReader.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}
}
public static void line_write(File file2) {
try (OutputStream outputStream = new FileOutputStream(file2);
OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream, StandardCharsets.UTF_8);
PrintWriter printWriter = new PrintWriter(outputStreamWriter);
) {
while (true) {
String line_write = SCANNER.nextLine().trim();
if (line_write.trim().isEmpty()) {
System.out.println("end input");
break;
} else {
printWriter.println(line_write);
printWriter.flush();
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}