English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Rust 파일 및 IO

이 장에서는 Rust 언어의 I/O 작업.

명령줄 매개변수 수신

명령줄 프로그램은 컴퓨터 프로그램 가장 기본적인 존재 형태로, 거의 모든 운영체제가 명령줄 프로그램을 지원하며, 시각적 프로그램의 실행은 명령줄 메커니즘에 기반합니다.

명령줄 프로그램은 명령줄 환경에서의 매개변수를 수신할 수 있어야 하며, 이러한 매개변수들은 보통 명령줄 명령 뒤에 공백 문자로 구분되어 있습니다.

많은 언어(예: Java와 C)/C++환경 매개변수는 주 함수의 매개변수(보통 문자열 배열)로 프로그램에 전달됩니다. 하지만 Rust에서는 주 함수가 매개변수가 없는 함수이며, 환경 매개변수는 개발자가 std::env 모듈을 통해 꺼내야 하며, 과정은 매우 간단합니다:

fn main() {
    let args = std::env::args();
    println!("{:?}", args);
}

지금 프로그램을 직접 실행합니다:

Args { inner: ["D:\\rust\\greeting\\target\\debug\\greeting.exe"] }

이 결과보다 더 길 수도 있지만, 이는 정상입니다. Args 구조체는 Args 내부에 있는 inner 배열을 가지고 있으며, 현재 실행 중인 프로그램의 위치를 나타내는 유일한 문자열을 포함하고 있습니다.

하지만 이 데이터 구조는 이해하기 어렵습니다. 문제가 없습니다. 우리는 간단히 탐색할 수 있습니다:

fn main() {
    let args = std::env::args();
    for arg in args {
        println!("{}", arg);
    }
}

실행 결과:

D:\rust\greeting\target\debug\greeting.exe

일반 매개변수들은 탐색되는 데 사용되는 것이 아닌가요.

지금까지 거의 만지지 않았던 launch.json 파일을 엽니다., "args": []를 찾아서, 여기서 실행 시 매개변수를 설정할 수 있습니다. 우리는 그것을 "args": ["first", "second"]로 작성하고, 다시 프로그램을 실행합니다. 실행 결과:

D:\rust\greeting\target\debug\greeting.exe
first
second

정말로의 명령줄 프로그램으로서, 우리는 그것을 사용한 적이 없었고, 언어 교재로서 명령줄을 통해 Rust 프로그램을 실행하는 방법에 대해 설명하지 않습니다. 하지만 당신이 훈련된 개발자라면, 실행 파일의 위치를 찾을 수 있어야 하며, 디렉토리에 접속하여 명령줄 명령을 사용하여 프로그램이 명령줄 환경 매개변수를 수신하는지 테스트할 수 있습니다.

명령행 입력

초기 장절에서는 명령행에서 출력하는 방법을 자세히 설명했습니다. 이는 언어 학습의 필요성 때문입니다. 출력이 없으면 프로그램을 디버깅할 수 없기 때문에, 명령행에서 입력 정보를 얻는 것은 명령행 프로그램에게도 매우 중요합니다.

Rust에서 std::io 모듈은 표준 입력(명령행 입력으로 간주될 수 있습니다)과 관련된 기능을 제공합니다:

use std::io::stdin;
fn main() {
let mut str_buf = String::new();
    stdin().read_line(&mut str_buf)
        .expect("Failed to read line.");
    println!("Your input line is 
{}", str_buf);
}

VSCode 환경이 명령행 입력을 지원하도록 설정하는 것은 매우 복잡한 일입니다. 플랫폼 간 문제와 디버깅 불가능한 문제가 있기 때문에, 우리는 VSCode 터미널에서 프로그램을 직접 실행합니다. 명령행에서 실행하면 다음과 같습니다:

D:\rust\greeting> cd ./target/debug
D:\rust\greeting\target\debug> ./greeting.exe
w3codebox
Your input line is 
w3codebox

std::io::Stdio는 read_line 메서드를 포함하고 있으며, 버퍼에 한 줄 문자열을 읽어들일 수 있으며, 읽기 중 발생하는 오류를 전달하는 Result 열거형 클래스를 반환합니다. 따라서 오류 처리를 위해 often expect 또는 unwrap 함수를 사용합니다.

주의:현재 Rust 표준 라이브러리는 명령행에서 숫자나 포맷된 데이터를 직접 읽는 방법을 제공하지 않습니다. 따라서 한 줄 문자열을 읽고 문자열 인식 함수를 사용하여 데이터를 처리할 수 있습니다.

파일 읽기

우리는 컴퓨터의 D:\ 디렉토리에 파일 text.txt를 만듭니다. 내용은 다음과 같습니다:

This is a text file.

이는 텍스트 파일 내용을 문자열에 读入하는 프로그램입니다:

use std::fs;
fn main() {
    let text = fs::read_to_string("D:\\text.txt").unwrap();
    println!("{}", text);
}

실행 결과:

This is a text file.

Rust에서 메모리에 맞춘 전체 파일을 읽는 것은 매우 간단합니다. std::fs 모듈의 read_to_string 메서드를 사용하여 텍스트 파일을 쉽게 읽을 수 있습니다.

但如果要读取的文件是二进制文件,我们可以用 std::fs::read 함수를 사용하여 u를 읽을 수 있습니다.8 타입 셋}}

use std::fs;
fn main() {
    let content = fs::read("D:\\text.txt").unwrap();
    println!("{:?}", content);
}

실행 결과:

[84, 104, 105, 115, 32, 105, 115, 32, 97, 32, 116, 101, 120, 116, 32, 102, 105, 108, 101, 46]

이 두 가지 방식은 단 한 번에 읽기로, 웹 애플리케이션 개발에 매우 적합합니다. 그러나 일부 하부 프로그램에서는 전통적인 스트림 읽기 방식이 대체할 수 없습니다. 왜냐하면 많은 경우 파일 크기가 메모리 용량을 초과할 수 있기 때문입니다.

Rust의 파일 스트림 읽기 방식:

use std::io::prelude::*;
use std::fs;
fn main() {
    let mut buffer = [0u8; 5];
    let mut file = fs::File::open("D:\\text.txt").unwrap();
    file.read(&mut buffer).unwrap();
    println!("{:?}", buffer);
    file.read(&mut buffer).unwrap();
    println!("{:?}", buffer);
}

실행 결과:

[84, 104, 105, 115, 32] 
[105, 115, 32, 97, 32]

std::fs 모듈의 File 클래스는 파일을 설명하는 클래스로, 파일을 열고, 파일을 열고 나서 버퍼에 파일의 아래 몇몇 바이트를 read 메서드를 사용하여 스트림으로 읽을 수 있습니다(버퍼는 u8 배열),읽은 바이트 수는 버퍼의 길이와 같습니다.

주의: VSCode는 현재 자동으로 표준 라이브러리 참조를 추가하는 기능이 없으므로, "함수나 메서드가 존재하지 않음"과 같은 오류가 표준 라이브러리 참조 문제일 수 있습니다. 우리는 표준 라이브러리의 주석 문서(마우스를 올려다놓으면 나타납니다)를 확인하여 수동으로 표준 라이브러리를 추가할 수 있습니다.

std::fs::File의 open 메서드는 파일을 "읽기 전용"으로 열고, close 메서드는 없습니다. 이는 Rust 컴파일러가 파일이 더 이상 사용되지 않을 때 자동으로 파일을 닫을 수 있기 때문입니다.

파일 쓰기

파일 쓰기는 단 한 번에 쓰기와 스트림 쓰기로 나뉩니다. 스트림 쓰기는 파일을 열고, 열기 방식은 "새로 만들기"(create)와 "추가"(append) 두 가지가 있습니다.

단 한 번에 쓰기:

use std::fs;
fn main() {
    fs::write("D:\\text.txt", "FROM RUST PROGRAM")
        .unwrap();
}

이는 단 한 번에 읽는 것과 같이 간단하고 편리합니다. 프로그램을 실행하면 D:\text.txt 파일의 내용이 FROM RUST PROGRAM으로 재쓰여질 것입니다. 따라서 단 한 번에 쓰는 것은 주의하십시오! 이는 파일 내용을 직접 지우므로 (파일이 얼마나 크든 상관없이) 주의해야 합니다. 파일이 존재하지 않으면 파일을 생성합니다.

데이터를 스트림 방식으로 파일에 쓰려면 std::fs::File의 create 메서드를 사용할 수 있습니다:

use std::io::prelude::*;
use std::fs::File;
fn main() {
    let mut file = File::create("D:\\text.txt").unwrap();
    file.write(b"FROM RUST PROGRAM").unwrap();
}

이 프로그램은 이전 프로그램과 동일합니다.

주의:열린 파일은 File 메서드를 사용하기 위해 변경 가능한 변수에 반드시 저장되어야 합니다!

File 클래스에는 append 스태틱 메서드가 없지만, OpenOptions를 사용하여 특정 메서드로 파일을 열 수 있습니다:

use std::io::prelude::*;
use std::fs::OpenOptions;
fn main() -> std::io::Result<()> {
    
    let mut file = OpenOptions::new()
            .append(true).open("D:\\text.txt")?;
    file.write(b" APPEND WORD")?;
    Ok(())
}

실행된 후, D:\text.txt 파일 내용은 다음과 같이 될 것입니다:

FROM RUST 프로그램 애프엔드 워드

OpenOptions는 파일을 열기 위해 유연한 메서드입니다. append 권한 외에도 read 권한과 write 권한을 설정할 수 있습니다. 파일을 읽고 쓰기 권한으로 열고 싶다면 다음과 같이 작성할 수 있습니다:

use std::io::prelude::*;
use std::fs::OpenOptions;
fn main() -> std::io::Result<()> {
    
    let mut file = OpenOptions::new()
            .read(true).write(true).open("D:\\text.txt")?;
    file.write(b"COVER")?;
    Ok(())
}

실행된 후, D:\text.txt 파일 내용은 다음과 같이 될 것입니다:

COVERRUST 프로그램 애프엔드 워드