মরিচ 1.x ফাইল পড়ার এবং লেখার ডি-ফ্যাক্টো উপায় কী?


136

মরিচা তুলনামূলকভাবে নতুন হওয়ার সাথে সাথে আমি ফাইলগুলি পড়া এবং লেখার অনেকগুলি উপায় দেখেছি। অনেকগুলি অত্যন্ত অগোছালো স্নিপেটস যার সাথে তাদের ব্লগ এসেছিল এবং আমি যে উদাহরণগুলি পেয়েছি তার মধ্যে 99% (এমনকি স্ট্যাক ওভারফ্লোতেও) অস্থির বিল্ডগুলি থেকে কাজ করে যা আর কাজ করে না। এখন যে মরিচা স্থিতিশীল, ফাইল পড়া বা লেখার জন্য একটি সাধারণ, পঠনযোগ্য, অ-প্যানিকিং স্নিপেট কী?

এটি পাঠ্য ফাইলটি পড়ার ক্ষেত্রে কাজ করে এমন আমার কাছে সবচেয়ে কাছের এটি, তবে এটি এখনও সংকলন করছে না যদিও আমি মোটামুটি নিশ্চিত করেছি যে আমার যা কিছু করা উচিত তা অন্তর্ভুক্ত করেছি। এটি সমস্ত জায়গাগুলির Google+ এ আমি স্নিপেটের ভিত্তিতে তৈরি করেছি এবং আমি যে পরিবর্তন করেছি কেবল তা পুরানো BufferedReaderএখন ঠিক BufReader:

use std::fs::File;
use std::io::BufReader;
use std::path::Path;

fn main() {
    let path = Path::new("./textfile");
    let mut file = BufReader::new(File::open(&path));
    for line in file.lines() {
        println!("{}", line);
    }
}

সংকলকটি অভিযোগ করেছেন:

error: the trait bound `std::result::Result<std::fs::File, std::io::Error>: std::io::Read` is not satisfied [--explain E0277]
 --> src/main.rs:7:20
  |>
7 |>     let mut file = BufReader::new(File::open(&path));
  |>                    ^^^^^^^^^^^^^^
note: required by `std::io::BufReader::new`

error: no method named `lines` found for type `std::io::BufReader<std::result::Result<std::fs::File, std::io::Error>>` in the current scope
 --> src/main.rs:8:22
  |>
8 |>     for line in file.lines() {
  |>                      ^^^^^

সংক্ষেপে, আমি যা খুঁজছি তা হ'ল:

  • সংক্ষিপ্ততা
  • সুপাঠ্যতা
  • সমস্ত সম্ভাব্য ত্রুটি আবরণ
  • আতঙ্কিত হয় না

আপনি কীভাবে ফাইলটি পড়তে চান? আপনি যেভাবে দেখিয়েছেন, আপনি কি এটি লাইন-লাইন চান? আপনি কি এক স্ট্রিং এ সব চান? "একটি ফাইল পড়ার" একাধিক উপায় রয়েছে।
শেপমাস্টার

উভয় পদ্ধতিই ঠিক আছে। আমি ইচ্ছাকৃতভাবে এটি খোলা ছেড়ে। যদি এটি সমস্ত এক স্ট্রিংয়ে সংগ্রহ করা হয় তবে এটিকে একটি ভেক <স্ট্রিং> এ বিভক্ত করা তুচ্ছ এবং তদ্বিপরীত। সমাধানগুলির জন্য আমার অনুসন্ধানের এই মুহুর্তে, আমি কেবল মার্জিত, টু ডেট রাস্ট ফাইল I / O কোড যা কাজ করে তা দেখে খুশি হব।
জ্যারেড

3
বৈশিষ্ট্য ত্রুটি সম্পর্কে ( std::io::Read), নোট করুন যে মরিচায় আপনাকে অবশ্যই এমন বৈশিষ্ট্যগুলি আমদানি করতে হবে যা আপনি স্পষ্টভাবে ব্যবহার করবেন বলে আশা করছেন ; সুতরাং এখানে আপনি একটি use std::io::Read(যা use std::io::{Read,BufReader}দুটি ব্যবহার একত্রিত করার এক হতে পারে) মিস করছেন
ম্যাথিউ এম।

উত্তর:


197

আমি এখানে যে ফাংশনগুলি দেখি তাগুলির নিজস্ব কোনওটিই আতঙ্কিত হয় না তবে আমি ব্যবহার করছি expectকারণ কোন ধরণের ত্রুটি পরিচালনা করা আপনার অ্যাপ্লিকেশনটিতে সবচেয়ে উপযুক্ত হবে তা আমি জানি না। যান পড়া প্রোগ্রামিং ভাষা মরচে এর হ্যান্ডলিং ত্রুটি অধ্যায় বুঝতে উপযুক্তভাবে আপনার নিজের প্রোগ্রামে ব্যর্থতা হ্যান্ডেল করতে।

মরিচা 1.26 এবং তারপরে

আপনি যদি অন্তর্নিহিত বিশদ সম্পর্কে যত্ন নিতে না চান তবে পড়া এবং লেখার জন্য এক-লাইন ফাংশন রয়েছে।

একটি ফাইল পড়ুন String

use std::fs;

fn main() {
    let data = fs::read_to_string("/etc/hosts").expect("Unable to read file");
    println!("{}", data);
}

একটি হিসাবে একটি ফাইল পড়ুন Vec<u8>

use std::fs;

fn main() {
    let data = fs::read("/etc/hosts").expect("Unable to read file");
    println!("{}", data.len());
}

একটি ফাইল লিখুন

use std::fs;

fn main() {
    let data = "Some data!";
    fs::write("/tmp/foo", data).expect("Unable to write file");
}

মরিচা 1.0 এবং এরপরে

এই ফর্মগুলি এক Stringবা আপনার Vecজন্য বরাদ্দকৃত এক-লাইন ফাংশনগুলির চেয়ে কিছুটা ভার্বোজ , তবে এটি আরও শক্তিশালী যে আপনি বরাদ্দকৃত ডেটা পুনরায় ব্যবহার করতে পারবেন বা কোনও বিদ্যমান বস্তুর সাথে যুক্ত করতে পারেন।

তথ্য পড়া

একটি ফাইল পড়ার জন্য দুটি মূল টুকরো দরকার: Fileএবং Read

একটি ফাইল পড়ুন String

use std::fs::File;
use std::io::Read;

fn main() {
    let mut data = String::new();
    let mut f = File::open("/etc/hosts").expect("Unable to open file");
    f.read_to_string(&mut data).expect("Unable to read string");
    println!("{}", data);
}

একটি হিসাবে একটি ফাইল পড়ুন Vec<u8>

use std::fs::File;
use std::io::Read;

fn main() {
    let mut data = Vec::new();
    let mut f = File::open("/etc/hosts").expect("Unable to open file");
    f.read_to_end(&mut data).expect("Unable to read data");
    println!("{}", data.len());
}

একটি ফাইল লিখুন

আমরা Writeবৈশিষ্ট্যটি ব্যবহার না করে এবং আমরা সর্বদা বাইটগুলি লিখি except আপনি এর সাথে বাইট String/ এ রূপান্তর করতে পারেন :&stras_bytes

use std::fs::File;
use std::io::Write;

fn main() {
    let data = "Some data!";
    let mut f = File::create("/tmp/foo").expect("Unable to create file");
    f.write_all(data.as_bytes()).expect("Unable to write data");
}

বাফার্ড আই / ও

সম্প্রদায়টি ব্যবহার করার জন্য BufReaderএবং BufWriterকোনও ফাইল থেকে সরাসরি পড়ার পরিবর্তে কিছুটা ধাক্কা অনুভব করেছি

একটি বাফার রিডার (বা লেখক) I / O অনুরোধের সংখ্যা হ্রাস করতে একটি বাফার ব্যবহার করে। উদাহরণস্বরূপ, একবার 256 বার ডিস্ক অ্যাক্সেস না করে 256 বাইট পড়ার জন্য ডিস্কটি একবারে অ্যাক্সেস করা অনেক বেশি দক্ষ।

বলা হচ্ছে, আমি বিশ্বাস করি না যে পুরো ফাইলটি পড়ার সময় কোনও বাফার রিডার / লেখক কার্যকর হবে। read_to_endকিছুটা বড় অংশগুলিতে ডেটা অনুলিপি করে বলে মনে হচ্ছে, তাই স্থানান্তরটি ইতিমধ্যে কম I / O অনুরোধগুলিতে প্রাকৃতিকভাবে coalesced হতে পারে।

এটি পড়ার জন্য এটি ব্যবহার করার উদাহরণ এখানে:

use std::fs::File;
use std::io::{BufReader, Read};

fn main() {
    let mut data = String::new();
    let f = File::open("/etc/hosts").expect("Unable to open file");
    let mut br = BufReader::new(f);
    br.read_to_string(&mut data).expect("Unable to read string");
    println!("{}", data);
}

এবং লেখার জন্য:

use std::fs::File;
use std::io::{BufWriter, Write};

fn main() {
    let data = "Some data!";
    let f = File::create("/tmp/foo").expect("Unable to create file");
    let mut f = BufWriter::new(f);
    f.write_all(data.as_bytes()).expect("Unable to write data");
}

BufReaderআপনি লাইন বাই লাইন পড়তে চাইলে এ আরও দরকারী:

use std::fs::File;
use std::io::{BufRead, BufReader};

fn main() {
    let f = File::open("/etc/hosts").expect("Unable to open file");
    let f = BufReader::new(f);

    for line in f.lines() {
        let line = line.expect("Unable to read line");
        println!("Line: {}", line);
    }
}

2
এটিকে ভিত্তি করার মতো আমার কাছে আসলে খুব বেশি কিছু নেই, তবে এটি গবেষণা করার সময় আমি সম্প্রদায় থেকে একটি ফাইল থেকে স্ট্রিংয়ের জন্য সরাসরি পড়ার পরিবর্তে বুফ্রাইডার এবং বুফউইটার ব্যবহার করার জন্য কিছুটা ধাক্কা অনুভব করেছি। আপনি নিজের উত্তরে দেখিয়েছেন এমন "আরও ধ্রুপদী" সংস্করণে এই জিনিসগুলি বা সেগুলি ব্যবহার করার পক্ষে এবং কৌশলগুলি সম্পর্কে আপনি অনেক কিছু জানেন?
জেরেড

@TheDaleks আমি আপনার প্রশ্ন অনুসরণ করছি না। b"foobar"বাইটের একটি অ্যারের একটি রেফারেন্স তৈরি করতে একটি আক্ষরিক আছে ( &[u8; N])। যেমনটি, এটি অপরিবর্তনীয়। এটি আপনাকে দেয় এমন কিছুই নেই যা আপনি সহজ পদ্ধতিতে করতে পারবেন না।
শেপমাস্টার

@ শেপমাস্টার মাঝে মধ্যে এনকোডেড স্ট্রিংয়ের পরিবর্তে বাইট-অ্যারে রাখা সুবিধাজনক; উদাহরণস্বরূপ, আপনি যদি এমন অ্যাপ তৈরি করতে চান যা ফাইলগুলিকে এক জায়গা থেকে অন্য স্থানে নিয়ে যায়, আপনার কাঁচা বাইট থাকা দরকার যাতে অ্যাপ্লিকেশনটি প্রক্রিয়াকরণযোগ্য ফাইলগুলিকে দুর্নীতি না করে।
দালেকস

@ দ্য ডালিক্স হ্যাঁ, এই কারণেই এই উত্তরটি কীভাবে Vec<u8>পড়তে এবং লেখার জন্য ব্যবহার করতে হয় তা ব্যাখ্যা করে । সেগুলি কাঁচা বাইট।
শেপমাস্টার
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.