আমি কীভাবে একটি সিডিএস :: স্ট্রিংয়ের পুরো ফাইলটি সি ++ তে পড়ব?


178

আমি কীভাবে একটি ফাইল পড়ব std::string, অর্থাৎ পুরো ফাইলটি একবারে পড়তে পারি?

পাঠক বা বাইনারি মোড কলার দ্বারা নির্দিষ্ট করা উচিত। সমাধানটি স্ট্যান্ডার্ড-কমপ্লায়েন্ট, পোর্টেবল এবং দক্ষ হওয়া উচিত। এটি অযথা স্ট্রিংয়ের ডেটা অনুলিপি করা উচিত নয় এবং স্ট্রিংটি পড়ার সময় এটি মেমরির পুনঃব্যবস্থাপনা এড়ানো উচিত।

ওয়ান ওয়ে এই কাজ করতে FILESIZE সূচনা করা, হবে মাপ পরিবর্তন std::stringএবং fread()মধ্যে std::stringএর const_cast<char*>()'ইডি data()। এর জন্য std::stringস্ট্যান্ডার্ড ডেটা সংহত হওয়া দরকার যা মানক দ্বারা প্রয়োজনীয় নয়, তবে এটি সমস্ত পরিচিত বাস্তবায়নের ক্ষেত্রে দেখা যায়। সবচেয়ে খারাপটি কী, যদি ফাইলটি পাঠ্য মোডে পাঠ করা হয় তবে std::stringএর আকার ফাইলের আকারের সমান নাও হতে পারে।

একটি সম্পূর্ণরূপে সঠিক, স্ট্যান্ডার্ড-কমপ্লায়েন্ট এবং পোর্টেবল সলিউশনগুলি এ std::ifstreamএর rdbuf()মধ্যে std::ostringstreamএবং সেখান থেকে একটিতে ব্যবহার করে নির্মিত যেতে পারে std::string। তবে এটি স্ট্রিং ডেটা অনুলিপি করতে পারে এবং / অথবা অযথা মেমরিটি পুনর্বিবেচনা করতে পারে।

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


void slurp(std::string& data, bool is_binary)

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

পাঠ্য এবং বাইনারি মোড হ'ল এমএসডিওএস এবং উইন্ডোজ নির্দিষ্ট হ্যাক যা নতুন লাইনের উইন্ডোজ (সিআর / এলএফ) দুটি অক্ষর দ্বারা প্রতিনিধিত্ব করা হয় এই সত্যটি পেতে চেষ্টা করে। পাঠ্য মোডে, এগুলিকে একটি অক্ষর হিসাবে চিহ্নিত করা হয় ('\ n')।
ফেরুক্সিও

1
যদিও (পুরোপুরি) হুবহু নকল নয়, এটির সাথে নিবিড়ভাবে সম্পর্কিত: একটি স্ট্রাইড :: স্ট্রিং অবজেক্টের জন্য কীভাবে মেমরিকে প্রাক-বরাদ্দ করা যায়? (যা উপরের কনরাদের বক্তব্যের বিপরীতে, এটি করার কোড অন্তর্ভুক্ত করে, কোনও অতিরিক্ত অনুলিপি না করে সরাসরি ফাইলটিকে গন্তব্যে পাঠানো)।
জেরি কফিন

1
"স্ট্যান্ডার্ডের সাথে সামঞ্জস্যপূর্ণ প্রয়োজন হয় না" - হ্যাঁ, এটি চক্রাকার পথে। আপনি স্ট্রিংয়ে op [] ব্যবহার করার সাথে সাথে এটি অবশ্যই একটি লিখিত বাফার বাফারে জড়িত হওয়া উচিত, সুতরাং আপনি যদি প্রথমে বড় আকারের () পরিবর্তন করেন তবে & str [0] এ লিখতে নিরাপদ গ্যারান্টিযুক্ত। এবং সি ++ 11 এ স্ট্রিংটি সর্বদা স্বচ্ছল।
টিনো দিদারিকসেন

2
সম্পর্কিত লিঙ্ক: সি ++ এ ফাইল পড়বেন কীভাবে? - মাপদণ্ড এবং বিভিন্ন পদ্ধতির আলোচনা। এবং হ্যাঁ, rdbuf(স্বীকৃত উত্তরের মধ্যে একটি) দ্রুততম নয় read,।
কিংবদন্তি 2 কে

উত্তর:


138

একটি উপায় হ'ল স্ট্রিম বাফারটিকে একটি পৃথক মেমরি স্ট্রিমে ফ্লাশ করা এবং তারপরে এটিকে রূপান্তর করুন std::string:

std::string slurp(std::ifstream& in) {
    std::ostringstream sstr;
    sstr << in.rdbuf();
    return sstr.str();
}

এটি সুন্দরভাবে সংক্ষিপ্ত। তবে, প্রশ্নটিতে উল্লিখিত হিসাবে এটি একটি অপ্রয়োজনীয় অনুলিপি সম্পাদন করে এবং দুর্ভাগ্যক্রমে এই অনুলিপিটি গোপন করার কোনও উপায় নেই।

দুর্ভাগ্যক্রমে, একমাত্র আসল সমাধান যা অপ্রয়োজনীয় অনুলিপিগুলি এড়িয়ে চলে man যেহেতু সি ++ এর এখন সুসংগত স্ট্রিংয়ের গ্যারান্টি রয়েছে তাই যে কেউ নিম্নলিখিতটি লিখতে পারে (+C ++ 14):

auto read_file(std::string_view path) -> std::string {
    constexpr auto read_size = std::size_t{4096};
    auto stream = std::ifstream{path.data()};
    stream.exceptions(std::ios_base::badbit);

    auto out = std::string{};
    auto buf = std::string(read_size, '\0');
    while (stream.read(& buf[0], read_size)) {
        out.append(buf, 0, stream.gcount());
    }
    out.append(buf, 0, stream.gcount());
    return out;
}

20
এটিকে অনলাইনার করার কী লাভ? আমি সর্বদা স্পষ্টতামূলক কোড বেছে নেব। একজন স্ব-অধ্যাপক ভিবি.নেট উত্সাহী (আইআইআরসি) হিসাবে আমি মনে করি আপনার অনুভূতিটি বোঝা উচিত?
sehe

5
@ সেহ: আমি আশা করব যে কোনও অর্ধে-সক্ষম সি ++ কোডার সহজেই ওয়ান-লাইন বুঝতে পারবেন। অন্যান্য জিনিস প্রায় কাছাকাছি থাকার তুলনায় এটি বেশ কদর্য।
দেবসোলার

43
@ দেবসোলার ওয়েল, আরও সুস্পষ্ট সংস্করণটি 30% কম খাটো, একটি কাস্টের অভাব রয়েছে এবং অন্যথায় সমতুল্য। আমার প্রশ্নটি তাই দাঁড়ায়: "এটিকে অনেলাইনার করার কী লাভ?"
sehe

13
দ্রষ্টব্য: এই পদ্ধতিটি স্ট্রিংস্ট্রিমের বাফারে ফাইলটি পড়ে, তারপরে সেই পুরো বাফারটি অনুলিপি করে string। অর্থাৎ অন্যান্য কয়েকটি বিকল্পের দ্বিগুণ মেমরির প্রয়োজন। (বাফারটি সরানোর কোনও উপায় নেই)। একটি বৃহত ফাইলের জন্য এটি একটি উল্লেখযোগ্য জরিমানা হবে, সম্ভবত এমনকি একটি বরাদ্দ ব্যর্থতাও ঘটায়।
এমএম

9
@ ড্যানিসিসনবাউম আপনি কিছু বিভ্রান্ত করছেন। প্রোগ্রামিংয়ে সংক্ষিপ্ততা সত্যই গুরুত্বপূর্ণ, তবে এটি অর্জনের সঠিক উপায়টি সমস্যাটিকে বিভিন্ন অংশে বিভক্ত করা এবং সেগুলি স্বাধীন ইউনিটে (ফাংশন, ক্লাস, ইত্যাদি) আবদ্ধ করা। ফাংশন যুক্ত করা সংক্ষিপ্ততা থেকে বিরত হয় না; পুরোপুরি বিপরীত.
কনরাড রুডল্ফ

52

একই উত্তর এই উত্তর দেখুন ।

আপনার সুবিধার জন্য, আমি সিটিটির সমাধানটি পুনরায় পোস্ট করছি:

string readFile2(const string &fileName)
{
    ifstream ifs(fileName.c_str(), ios::in | ios::binary | ios::ate);

    ifstream::pos_type fileSize = ifs.tellg();
    ifs.seekg(0, ios::beg);

    vector<char> bytes(fileSize);
    ifs.read(bytes.data(), fileSize);

    return string(bytes.data(), fileSize);
}

মবি ডিকের পাঠ্য (১.৩ এম) এর বিপরীতে গড়ে ১০০ রান সংগ্রহ করার সময়, এখানে উপস্থাপিত অন্যান্য উত্তরের তুলনায় এই সমাধানটি প্রায় 20% দ্রুত সম্পাদন বার হিসাবে তৈরি হয়েছিল। পোর্টেবল সি ++ সমাধানের জন্য খারাপ নয়, আমি ফাইলটি এমএমপ করার ফলাফল দেখতে চাই;)


3
সম্পর্কিত: বিভিন্ন পদ্ধতির সময়ের পারফরম্যান্স তুলনা: সি ++
jfs

12
আজ অবধি, আমি কখনও টেলজি () নন-ফাইলাইজ ফলাফলের প্রতিবেদন করতে দেখিনি। বাগের উত্স খুঁজতে আমাকে কয়েক ঘন্টা সময় নিয়েছে। ফাইলের আকার পেতে দয়া করে টেলগ () ব্যবহার করবেন না। stackoverflow.com/questions/22984956/...
Puzomor ক্রোয়েশিয়া

আপনি ifs.seekg(0, ios::end)আগে কল করা উচিত নয় tellg? ফাইল রিডিং পয়েন্টার খোলার ঠিক পরে শুরু হয় এবং তাই tellgশূন্য ফিরে আসে
Andriy Tylychko

1
এছাড়াও আপনি হিসাবে আপনি dereference করব খালি ফাইল চেক করতে হবে nullptrদ্বারা&bytes[0]
আন্দ্রেই Tylychko

ঠিক আছে, আমি মিস করেছি ios::ate, সুতরাং আমি মনে করি যে স্পষ্টভাবে প্রান্তে চলে যাওয়া একটি সংস্করণ আরও পাঠযোগ্য হবে
Andriy Tylychko

50

সংক্ষিপ্ত রূপ: Live On Coliru

std::string str(std::istreambuf_iterator<char>{ifs}, {});

এটি শিরোনাম প্রয়োজন <iterator>

কিছু যে রিপোর্ট এই পদ্ধতি স্ট্রিং preallocating এবং ব্যবহার তুলনায় ধীর হয় ছিল std::istream::read। তবে, অপটিমাইজেশন সক্ষম একটি আধুনিক সংকলকটিতে এটি এখন আর এটি বলে মনে হয় না, যদিও বিভিন্ন পদ্ধতির আপেক্ষিক কার্য সম্পাদন অত্যন্ত সংকলক নির্ভর করে বলে মনে হয়।


7
আপনি এই উত্তর সন্ধান করতে পারে? এটি কতটা কার্যকরী, এটি কীভাবে স্ট্র্যাং মেমরির পূর্বপরিবর্তন করতে কোনও সময় কোনও ফাইলের চর পড়তে পারে?
মার্টিন বেকেট

@ এমএম আমি যে তুলনাটি পড়ছি, এই পদ্ধতিটি খাঁটি সি ++-এ-প্রিলোকটেড-বাফার পদ্ধতির চেয়ে ধীর।
কনরাড রুডল্ফ

আপনি ঠিক বলেছেন, এটি শিরোনামটি কোডের নমুনার অধীনে থাকার চেয়েও তার চেয়ে বেশি নয় :)
এমএম

@ জজলিন সি ++ এর মতো কাজ করে না। নির্দিষ্ট পরিবেশে শিরোনামের প্রয়োজন না থাকা আপনার এটি অন্তর্ভুক্ত না করার পক্ষে ভাল কারণ নয়।
এলএফ

এই পদ্ধতিটি কি বহু বারের জন্য মেমরি পুনঃস্থাপনকে ট্রিগার করবে?
মুদ্রা

22

ব্যবহার

#include <iostream>
#include <sstream>
#include <fstream>

int main()
{
  std::ifstream input("file.txt");
  std::stringstream sstr;

  while(input >> sstr.rdbuf());

  std::cout << sstr.str() << std::endl;
}

বা খুব কাছাকাছি কিছু। নিজেকে ডাবল-চেক করার জন্য আমার কাছে স্টডিলিব রেফারেন্স নেই।

হ্যাঁ, আমি বুঝতে পারি আমি slurpঅনুরোধ অনুযায়ী ফাংশনটি লিখিনি ।


এটি দেখতে দুর্দান্ত দেখাচ্ছে তবে এটি সংকলন করে না। এটি সংকলন করার পরিবর্তনগুলি এটিকে এই পৃষ্ঠার অন্যান্য উত্তরে হ্রাস করে। আইডোন
জেডিম্যাটটিও

5
কেন লুপ?
জিতরেক্স

একমত। যখন এটি operator>>পড়েন std::basic_streambuf, এটি ইনপুট স্ট্রিমটি (কী বাকী থাকবে) গ্রাস করবে, সুতরাং লুপটি অপ্রয়োজনীয়।
রেমি লিউউ

15

আপনার যদি সি ++ 17 (স্টাডি :: ফাইল সিস্টেম) থাকে তবে এই উপায়টিও রয়েছে (যা ফাইলের আকারের std::filesystem::file_sizeপরিবর্তে seekgএবং এর পরিবর্তে পায় tellg):

#include <filesystem>
#include <fstream>
#include <string>

namespace fs = std::filesystem;

std::string readFile(fs::path path)
{
    // Open the stream to 'lock' the file.
    std::ifstream f(path, std::ios::in | std::ios::binary);

    // Obtain the size of the file.
    const auto sz = fs::file_size(path);

    // Create a buffer.
    std::string result(sz, '\0');

    // Read the whole file into the buffer.
    f.read(result.data(), sz);

    return result;
}

দ্রষ্টব্য : আপনার ব্যবহারের প্রয়োজন হতে পারে <experimental/filesystem>এবং std::experimental::filesystemযদি আপনার স্ট্যান্ডার্ড লাইব্রেরি এখনও পুরোপুরি সি ++ 17 সমর্থন করে না। এছাড়াও আপনি প্রতিস্থাপন করতে প্রয়োজন হতে পারে result.data()সঙ্গে &result[0]যদি এটা সমর্থন করে না অ const এসটিডি :: basic_string তথ্য


1
এটি অনির্ধারিত আচরণের কারণ হতে পারে; পাঠ্য মোডে ফাইলটি খোলার ফলে কিছু অপারেটিং সিস্টেমের ডিস্ক ফাইলের চেয়ে আলাদা স্ট্রিম পাওয়া যায়।
এমএম

1
মূলত boost::filesystemএমনভাবে বিকাশ হয়েছে যাতে আপনি সি ++ 17 না থাকলে আপনিও বুস্ট ব্যবহার করতে পারেন
গারহার্ড বার্গার

2
একটি এপিআই দিয়ে একটি ফাইল খোলার এবং অন্যটির আকারের আকার পাওয়া অসম্পূর্ণতা এবং বর্ণের অবস্থার জন্য বলে মনে হচ্ছে।
আর্থার ট্যাকা

14

ব্যবহারের প্রতিক্রিয়াগুলিতে সরাসরি মন্তব্য করার মতো যথেষ্ট খ্যাতি আমার নেই tellg()

দয়া করে সচেতন হন যে tellg()ত্রুটিতে -1 ফিরে আসতে পারে । যদি আপনি ফলাফল পাস হয়tellg() বরাদ্দ প্যারামিটার হিসাবে প্রথমে ফলাফলটি পরীক্ষা করা উচিত।

সমস্যার উদাহরণ:

...
std::streamsize size = file.tellg();
std::vector<char> buffer(size);
...

উপরের উদাহরণে, tellg()কোনও ত্রুটির মুখোমুখি হলে এটি -1 ফিরে আসবে। স্বাক্ষরযুক্ত (অর্থাত্ ফলাফল tellg()) এবং স্বাক্ষরবিহীন (অর্থাত্ vector<char>নির্মাণকারীর কাছে আর্গ) এর মধ্যে অন্তর্নিহিত কাস্টিংয়ের ফলস্বরূপ আপনার ভেক্টর ভুলভাবে খুব বড় সংখ্যক বাইটগুলি বরাদ্দ করবে । (সম্ভবত 4294967295 বাইট, বা 4 জিবি)

উপরের অ্যাকাউন্টের জন্য প্যাক্সোস 1977 এর উত্তরটি সংশোধন করা হচ্ছে:

string readFile2(const string &fileName)
{
    ifstream ifs(fileName.c_str(), ios::in | ios::binary | ios::ate);

    ifstream::pos_type fileSize = ifs.tellg();
    if (fileSize < 0)                             <--- ADDED
        return std::string();                     <--- ADDED

    ifs.seekg(0, ios::beg);

    vector<char> bytes(fileSize);
    ifs.read(&bytes[0], fileSize);

    return string(&bytes[0], fileSize);
}

5

এই সমাধানটি rdbuf () - ভিত্তিক পদ্ধতিতে পরীক্ষা করতে ত্রুটি যুক্ত করে।

std::string file_to_string(const std::string& file_name)
{
    std::ifstream file_stream{file_name};

    if (file_stream.fail())
    {
        // Error opening file.
    }

    std::ostringstream str_stream{};
    file_stream >> str_stream.rdbuf();  // NOT str_stream << file_stream.rdbuf()

    if (file_stream.fail() && !file_stream.eof())
    {
        // Error reading file.
    }

    return str_stream.str();
}

আমি এই উত্তরটি যুক্ত করছি কারণ আসল পদ্ধতিতে ত্রুটি-চেক যোগ করা আপনার প্রত্যাশার মতো তুচ্ছ নয়। মূল পদ্ধতিটি স্ট্রিংস্ট্রিমের সন্নিবেশ অপারেটর ব্যবহার করে (str_stream << file_stream.rdbuf() ) ব্যবহার করে। সমস্যাটি হ'ল কোনও অক্ষর inোকানো না হলে এটি স্ট্রিংস্ট্রিমের ব্যর্থতা সেট করে। এটি কোনও ত্রুটির কারণে হতে পারে বা ফাইলটি খালি থাকার কারণে হতে পারে। আপনি যদি ব্যর্থতাকে পর্যবেক্ষণ করে ব্যর্থতা পরীক্ষা করে থাকেন, আপনি খালি ফাইলটি পড়লে আপনার একটি মিথ্যা ইতিবাচক মুখোমুখি হবে। ফাইলটি খালি থাকায় আপনি কোনও অক্ষর সন্নিবেশ করতে বৈধ ব্যর্থতা এবং কোনও অক্ষর সন্নিবেশ করতে "ব্যর্থতা" কীভাবে নিষ্ক্রিয় করবেন?

আপনি খালি ফাইলের জন্য স্পষ্টভাবে পরীক্ষা করার জন্য ভাবতে পারেন, তবে এটি আরও কোড এবং সম্পর্কিত ত্রুটি পরীক্ষা করে।

ব্যর্থতার শর্তটি পরীক্ষা করা হচ্ছে str_stream.fail() && !str_stream.eof() হয় না, কারণ সন্নিবেশ অপারেশনটি ইওফবিট সেট করে না (ostringstream বা ifstream এ)।

সুতরাং, সমাধানটি হ'ল অপারেশন পরিবর্তন করা। অস্ট্রিংস্ট্রিমের সন্নিবেশ অপারেটর (<<) ব্যবহার না করে, ifstream এর নিষ্কাশন অপারেটর (>>) ব্যবহার করুন, যা ইওফিট সেট করে। তারপরে ব্যর্থতার শর্তটি পরীক্ষা করুন file_stream.fail() && !file_stream.eof()

গুরুত্বপূর্ণভাবে, যখন file_stream >> str_stream.rdbuf()কোনও বৈধ ব্যর্থতার মুখোমুখি হয় , তখন এটি কখনও eofbit সেট করা উচিত নয় (স্পেসিফিকেশন সম্পর্কে আমার বোঝার অনুসারে)। এর অর্থ বৈধ ব্যর্থতা সনাক্ত করতে উপরের চেকটি যথেষ্ট।


3

এর মতো কিছু খুব খারাপ হওয়া উচিত নয়:

void slurp(std::string& data, const std::string& filename, bool is_binary)
{
    std::ios_base::openmode openmode = ios::ate | ios::in;
    if (is_binary)
        openmode |= ios::binary;
    ifstream file(filename.c_str(), openmode);
    data.clear();
    data.reserve(file.tellg());
    file.seekg(0, ios::beg);
    data.append(istreambuf_iterator<char>(file.rdbuf()), 
                istreambuf_iterator<char>());
}

এখানে সুবিধাটি হ'ল আমরা প্রথমে রিজার্ভ করি তাই জিনিসগুলি পড়ার সাথে সাথে স্ট্রিংটি বাড়িয়ে তুলতে হবে না The অসুবিধাটি হ'ল আমরা এটি চর দ্বারা করে করি। একটি স্মার্ট সংস্করণ পুরো পঠিত বাফটিকে ধরে ফেলতে পারে এবং তারপরে আন্ডারফ্লোতে কল করতে পারে।


1
আপনার এই কোডটির সংস্করণটি চেকআউট করা উচিত যা স্ট্রিংয়ের পরিবর্তে প্রারম্ভিক পড়ার জন্য std :: ভেক্টর ব্যবহার করে। অনেক বেশি দ্রুত।
paxos1977

3

যুক্তিসঙ্গত দৃ error় ত্রুটি পরীক্ষা করে নতুন ফাইল সিস্টেম লাইব্রেরি ব্যবহার করে এখানে একটি সংস্করণ দেওয়া হয়েছে:

#include <cstdint>
#include <exception>
#include <filesystem>
#include <fstream>
#include <sstream>
#include <string>

namespace fs = std::filesystem;

std::string loadFile(const char *const name);
std::string loadFile(const std::string &name);

std::string loadFile(const char *const name) {
  fs::path filepath(fs::absolute(fs::path(name)));

  std::uintmax_t fsize;

  if (fs::exists(filepath)) {
    fsize = fs::file_size(filepath);
  } else {
    throw(std::invalid_argument("File not found: " + filepath.string()));
  }

  std::ifstream infile;
  infile.exceptions(std::ifstream::failbit | std::ifstream::badbit);
  try {
    infile.open(filepath.c_str(), std::ios::in | std::ifstream::binary);
  } catch (...) {
    std::throw_with_nested(std::runtime_error("Can't open input file " + filepath.string()));
  }

  std::string fileStr;

  try {
    fileStr.resize(fsize);
  } catch (...) {
    std::stringstream err;
    err << "Can't resize to " << fsize << " bytes";
    std::throw_with_nested(std::runtime_error(err.str()));
  }

  infile.read(fileStr.data(), fsize);
  infile.close();

  return fileStr;
}

std::string loadFile(const std::string &name) { return loadFile(name.c_str()); };

infile.openstd::stringরূপান্তর না করেও গ্রহণ করতে পারে.c_str()
ম্যাট এডিং

filepathনা std::stringএটি, এটি একটি std::filesystem::path। দেখা যাচ্ছে যেগুলির মধ্যে একটিরও std::ifstream::openগ্রহণ করতে পারে।
ডেভিড জি

@ ডেভিডজি, স্পষ্টত std::filesystem::pathরূপান্তরিতstd::string
জেফ্রি ক্যাশ

সিপ্রেফারেন্স ডট কম অনুসারে, সেই ::openসদস্য ফাংশনটি std::ifstreamগ্রহণ std::filesystem::pathকরে যে ::c_str()পদ্ধতিতে পথে ডাকা হয়েছিল। ::value_typeপাথের অন্তর্নিহিতটি charপসিক্সের অধীনে।
ডেভিড জি

2

আপনি 'স্টাডি :: গেটলাইন' ফাংশনটি ব্যবহার করতে পারেন এবং 'ইওফ' ডিলিমিটার হিসাবে নির্দিষ্ট করতে পারেন। ফলাফল কোডটি কিছুটা অস্পষ্ট যদিও:

std::string data;
std::ifstream in( "test.txt" );
std::getline( in, data, std::string::traits_type::to_char_type( 
                  std::string::traits_type::eof() ) );

5
আমি কেবল এটি পরীক্ষা করেছি, এটি ফাইলের আকার পাওয়া এবং পুরো ফাইলের আকারের জন্য বাফারে পড়ার কলিংয়ের চেয়ে অনেক ধীর গতির বলে মনে হয়। 12x ধীরের আদেশে।
ডেভিড

এটি কেবল তখনই কাজ করবে, যতক্ষণ না আপনার ফাইলে "ইওফ" (যেমন 0x00, 0xff, ...) অক্ষর নেই। যদি থাকে তবে আপনি কেবল ফাইলটির কিছু অংশ পড়বেন।
ওলাফ ডিয়েটশে

2

স্টাড :: স্ট্রিংয়ের কনস্ট চর * বাফারে কখনও লিখবেন না। কখনই না! এটি করা একটি বিশাল ভুল।

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


5
যেহেতু সি ++ 11 এটি সরাসরি std::stringবাফারে লিখতে ঠিক হবে বলে গ্যারান্টিযুক্ত ; এবং আমি বিশ্বাস করি যে এটির আগে সমস্ত বাস্তব বাস্তবায়নের উপর সঠিকভাবে কাজ করেছিল
এমএম

1
সি ++ 17 যেহেতু আমাদের কাছে std::string::data()স্ট্রিং বাফারকে সরাসরি পরিবর্তনের মতো কৌশলগুলি অবলম্বন না করে পরিবর্তনের জন্য অবিচ্ছিন্ন পদ্ধতি রয়েছে &str[0]
zett42

@ Zett42 এর সাথে সম্মত এই উত্তরটি সত্যই ভুল
জেরেমিওং

0
#include <string>
#include <sstream>

using namespace std;

string GetStreamAsString(const istream& in)
{
    stringstream out;
    out << in.rdbuf();
    return out.str();
}

string GetFileAsString(static string& filePath)
{
    ifstream stream;
    try
    {
        // Set to throw on failure
        stream.exceptions(fstream::failbit | fstream::badbit);
        stream.open(filePath);
    }
    catch (system_error& error)
    {
        cerr << "Failed to open '" << filePath << "'\n" << error.code().message() << endl;
        return "Open fail";
    }

    return GetStreamAsString(stream);
}

ব্যবহার:

const string logAsString = GetFileAsString(logFilePath);

0

সিটিটি-র সমাধানের ভিত্তিতে একটি আপডেট ফাংশন:

#include <string>
#include <fstream>
#include <limits>
#include <string_view>
std::string readfile(const std::string_view path, bool binaryMode = true)
{
    std::ios::openmode openmode = std::ios::in;
    if(binaryMode)
    {
        openmode |= std::ios::binary;
    }
    std::ifstream ifs(path.data(), openmode);
    ifs.ignore(std::numeric_limits<std::streamsize>::max());
    std::string data(ifs.gcount(), 0);
    ifs.seekg(0);
    ifs.read(data.data(), data.size());
    return data;
}

দুটি গুরুত্বপূর্ণ পার্থক্য রয়েছে:

tellg()ফাইল শুরুর পর থেকে অফসেটটি বাইটে ফেরত দেওয়ার গ্যারান্টি নেই। পরিবর্তে, পুজমোর ক্রোয়েশিয়া যেমন উল্লেখ করেছে, এটি আরও একটি টোকেন যা প্রবাহ কলগুলির মধ্যে ব্যবহার করা যেতে পারে। gcount()তবে সর্বশেষে নিষ্কাশন করা বাইটের পরিমাণ ফিরে আসে । অতএব আমরা ফাইলটি খুলি, ফাইলের ignore()আকার পেতে তার সমস্ত বিষয়বস্তু উত্তোলন এবং বাতিল করি এবং তার ভিত্তিতে আউটপুট স্ট্রিংটি তৈরি করি।

দ্বিতীয়ত, আমরা একটি থেকে ফাইল ডাটা কপি করার থাকার এড়াতে std::vector<char>একটি থেকে std::stringস্ট্রিং সরাসরি লিখে।

পারফরম্যান্সের শর্তাবলী, এটি যথার্থতম দ্রুত হওয়া উচিত, সময়ের আগে উপযুক্ত আকারের স্ট্রিং বরাদ্দ করা এবং read()একবার কল করা । একটি আকর্ষণীয় সত্য হিসাবে, ব্যবহার ignore()এবং countg()পরিবর্তে ateএবং tellg()জিসিসি উপর নেমে প্রনয়ন প্রায় একই জিনিস , অল্পে অল্পে।


1
এই কোডটি কাজ করে না, আমি খালি স্ট্রিং পাচ্ছি। আমি মনে করি আপনি ifs.seekg(0)পরিবর্তে চেয়েছিলেন ifs.clear()(তারপরে এটি কার্যকর হয়)।
Xeverous

-1
#include <iostream>
#include <fstream>
#include <string.h>
using namespace std;
main(){
    fstream file;
    file.open("test.txt");
    string copy,temp;
    while(getline(file,temp)){
        copy+=temp;
        copy+="\n";
    }
    cout<<copy;
    file.close();
}

1
বিবরণ যোগ করুন।
পিটার

দয়া করে ভিজিট করুন এবং কোনও প্রশ্নের উত্তর কীভাবে তা পরীক্ষা করুন ।
ইউনূস তেমুরলেঙ্ক
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.