স্কালায় পুরো ফাইল পড়বেন?


312

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

আমি যে সেরাটি নিয়ে আসতে পারি তা হ'ল:

scala.io.Source.fromPath("file.txt").getLines.reduceLeft(_+_)

বা আমার জাভা-র godশ্বর্যজনক প্রতিমা ব্যবহার করার কথা রয়েছে , যার মধ্যে সবচেয়ে ভাল (বাহ্যিক লাইব্রেরি ব্যবহার না করে) বলে মনে হচ্ছে:

import java.util.Scanner
import java.io.File
new Scanner(new File("file.txt")).useDelimiter("\\Z").next()

মেলিং তালিকার আলোচনার পড়া থেকে, আমার কাছে এটি স্পষ্ট নয় যে স্কালা.ইও.সোর্সটি এমনকি ক্যানোনিকাল আই / ও লাইব্রেরি হওয়ার কথা। আমি ঠিক বুঝতে পারি না এর উদ্দেশ্যকৃত উদ্দেশ্যটি ঠিক কী।

... আমি মৃত-সহজ এবং মনে রাখা সহজ কিছু চাই। উদাহরণস্বরূপ, এই ভাষাগুলিতে আইডিয়ামটি ভুলে যাওয়া খুব কঠিন ...

Ruby    open("file.txt").read
Ruby    File.read("file.txt")
Python  open("file.txt").read()

12
আপনি সঠিক সরঞ্জামগুলি জানলে জাভা এতটা খারাপ নয়। org.apache.commons.io.FileUtils আমদানি করুন; FileUtils.readFileToString (নতুন ফাইল ("file.txt", "ইউটিএফ -8")
স্মার্টনাট 700

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

উত্তর:


429
val lines = scala.io.Source.fromFile("file.txt").mkString

যাইহোক, " scala." সত্যই প্রয়োজনীয় নয়, যেমন এটি সর্বদা সুযোগের মধ্যে থাকে এবং আপনি অবশ্যই অবশ্যই আইও এর বিষয়বস্তু পুরো বা আংশিকভাবে আমদানি করতে পারেন এবং "আইও" প্রিপেন্ড করা এড়াতে পারেন। খুব।

উপরের ফাইলটি অবশ্য খোলে। সমস্যা এড়াতে আপনার এটিকে বন্ধ করে দেওয়া উচিত:

val source = scala.io.Source.fromFile("file.txt")
val lines = try source.mkString finally source.close()

উপরের কোডটির সাথে আর একটি সমস্যা হ'ল এটি কার্যকর করার প্রকৃতির কারণে এটি ভয়াবহ ধীর। বড় ফাইলগুলির জন্য একটি ব্যবহার করা উচিত:

source.getLines mkString "\n"

48
আমি পার্টিতে খুব দেরি করে ফেলেছি, তবে আমি "io.File" ("/ etc / passwd") করতে পারি তা না জানার জন্য আমি ঘৃণা করব।
পিএসপি

28
@ এক্সটেম্পোর যদি আপনি সত্যিই নিজেকে কৃতজ্ঞ বলে মনে করেন তবে আমি দুঃখিত। আমি স্কালা ভাষার জন্য আপনার সমর্থনকে গভীরভাবে প্রশংসা করি এবং প্রতিবার যখন আপনি ব্যক্তিগতভাবে আমি উত্থাপিত কোনও সমস্যাটি দেখেছি, আমার যে কোনও সমস্যা রয়েছে তার সমাধানের পরামর্শ দিয়েছি বা আমাকে কিছু ব্যাখ্যা করেছি time আমি সুযোগটি নেব, তারপরে, scala.io কে শালীন এবং যোগ্য কিছুতে পরিণত করার জন্য আপনাকে ধন্যবাদ জানাতে। আমি এখন থেকে আমার ধন্যবাদ আরও সোচ্চার হতে হবে, কিন্তু আমি এখনও নাম ঘৃণা করি, দুঃখিত।
ড্যানিয়েল সি সোব্রাল

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

15
ফাইল.রেড () একটি সুন্দর নাম হবে এবং পাশাপাশি রুবি এবং পাইথনের সাথে সামঞ্জস্য থাকবে।
ব্রেন্ডন ওকননর

26
@ এক্সটেম্পোর: আপনি মানুষকে অসন্তুষ্ট হতে থামাতে পারবেন না। তার ঠিক উপায় এটা. এটি আপনাকে বিরক্ত করবেন না যে কিছু লোক আপনার করা প্রতিটি পছন্দ পছন্দ করে না। এটাই কেবল জীবন, আপনি সবাইকে সন্তুষ্ট করতে পারবেন না :)
অ্যালেক্স বারানোস্কি

58

ড্যানিয়েলের সমাধানগুলিতে কেবল প্রসারিত করতে, আপনি ফাইলের ম্যানিপুলেশনের জন্য প্রয়োজনীয় যে কোনও ফাইলের মধ্যে নিম্নলিখিত আমদানি সন্নিবেশ করে জিনিসগুলি দুর্দান্তভাবে সংক্ষিপ্ত করতে পারেন:

import scala.io.Source._

এটি দিয়ে আপনি এখন এটি করতে পারেন:

val lines = fromFile("file.txt").getLines

আমি একটি সম্পূর্ণ ফাইল একটি একক মধ্যে পড়তে সতর্ক হতে হবে String। এটি একটি খুব খারাপ অভ্যাস, যা আপনাকে যত তাড়াতাড়ি এবং আপনার ভাবনার চেয়ে আরও শক্ততর কামড় দেবে। getLinesপদ্ধতি ধরনের একটি মান ফেরায়Iterator[String] । এটি কার্যকরভাবে ফাইলটিতে একটি অলস কার্সার, মেমরির আঠার ঝুঁকি না নিয়ে আপনাকে প্রয়োজনীয় ডেটা পরীক্ষা করার অনুমতি দেয়।

ওহ, এবং আপনার অন্তর্ভুক্ত প্রশ্নের উত্তর দেওয়ার জন্য Source: হ্যাঁ, এটি প্রচলিত আই / ও লাইব্রেরি। বেশিরভাগ কোডটি java.ioতার নিম্ন-স্তরের ইন্টারফেস এবং বিদ্যমান ফ্রেমওয়ার্কগুলির সাথে আরও ভাল সামঞ্জস্যতার কারণে ব্যবহার করে শেষ হয় , তবে যে কোনও কোডের পছন্দ রয়েছে তা Sourceবিশেষত সরল ফাইল ম্যানিপুলেশনের জন্য ব্যবহার করা উচিত ।


ঠিক আছে. উত্স সম্পর্কে আমার নেতিবাচক ছাপের জন্য একটি গল্প রয়েছে: আমি এখনকার চেয়ে একবারে অন্যরকম পরিস্থিতিতে ছিলাম, যেখানে আমার একটি খুব বড় ফাইল ছিল যা স্মৃতিতে খাপ খায় না। উত্স ব্যবহারের ফলে প্রোগ্রামটি ক্রাশ হয়ে গেছে; দেখা গেল এটি একবারে পুরো জিনিসটি পড়ার চেষ্টা করছে।
ব্রেন্ডন ওকননর

7
উত্স পুরো ফাইলটি মেমোরিতে পড়ার কথা নয়। আপনি যদি getLines, বা অন্য কোনও পদ্ধতি যা সংগ্রহ তৈরি করবে তার পরে যদি তালিকাগুলি ব্যবহার করেন তবে আপনি সমস্ত কিছু মেমোরিতে পাবেন। এখন, উত্স হ্যাক , কাজটি করার উদ্দেশ্যে, একটি সাবধানতার সাথে চিন্তা-ভাবনা লাইব্রেরি নয়। এটি স্কেলা ২.৮-তে উন্নত হবে, তবে স্কালার সম্প্রদায়ের পক্ষে ভাল আই / ও এপিআই সংজ্ঞায়নে সক্রিয় হওয়ার নিশ্চয় সুযোগ রয়েছে।
ড্যানিয়েল সি। সোব্রাল

36
// for file with utf-8 encoding
val lines = scala.io.Source.fromFile("file.txt", "utf-8").getLines.mkString

6
আসল উত্তরে "গেটলাইনস" যুক্ত করা সমস্ত নতুনলাইন সরিয়ে দেবে। "Source.fromFile (" file.txt "," utf-8 ") হওয়া উচিত। MkString"।
জো 23

9
ড্যানিয়েল সি সোব্রালের উত্তরে আমার মন্তব্যটিও দেখুন - এটি ব্যবহারের ফলে উত্সটি বন্ধ হবে না, সুতরাং স্কালা ফাইলটিতে একটি লক ধরে রাখতে পারে।
ডিজেবি

26

(সম্পাদনা: এটি স্কেলা ২.৯-এ কাজ করে না এবং সম্ভবত ২.৮ হয় না)

ট্রাঙ্ক ব্যবহার করুন:

scala> io.File("/etc/passwd").slurp
res0: String = 
##
# User Database
# 
... etc

14
" slurp"? আমরা কি সত্যই স্বজ্ঞাত, স্বজ্ঞাত নাম দিচ্ছি? সমস্যাটি slurpহ'ল এটিকে সত্যিকারের পরে বোঝা যায়, ইংরেজী সহ প্রথম ব্যক্তির ভাষা কমপক্ষে, তবে আপনি এটি কখনই শুরু করবেন বলে ভাবেন না!
ড্যানিয়েল সি সোব্রাল

5
এই প্রশ্ন / উত্তরে কেবল হোঁচট খেয়েছে। Fileএখন আর ২.৮.০ এ নেই, তাই না?
huynhjl

4
স্লুর্প দুর্দান্ত শোনাচ্ছে। :) আমি এটি আশা করবো না, তবে আমি স্ক্রিনের আউটপুটটিকে 'মুদ্রণ' নামকরণ করার আশা করিনি। slurpচমৎকার! :) চমত্কার ছিল? আমি এটি খুঁজে না। ; (
ব্যবহারকারী অজানা

5
স্কেলা-২.১০.০ এ প্যাকেজের নামটি স্কেলা.রেফলেক.আই. ফাইল এবং এই "ফাইল" সম্পর্কে একটি প্রশ্ন। বাহিরে, কেন এই ফাইলটিকে "পরীক্ষামূলক" হিসাবে চিহ্নিত করা হয়েছে? এটি নিরাপদ? এটি ফাইল সিস্টেমে কোনও লক মুক্ত করে তোলে?
ভ্যাসিলিনোভিকভ

4
এই উদ্দেশ্যটির উদ্ভবের জন্য স্লার্পের দীর্ঘ ইতিহাস রয়েছে, আমি মনে করি পার্ল থেকে
ক্রিস মাউন্টফোর্ড

18
import java.nio.charset.StandardCharsets._
import java.nio.file.{Files, Paths}

new String(Files.readAllBytes(Paths.get("file.txt")), UTF_8)

অক্ষর এনকোডিং এবং পরিষ্কার করার জন্য কোনও সংস্থান নেই নিয়ন্ত্রণ করুন। এছাড়াও, সম্ভবত অনুকূলিত করা হয়েছে (যেমন Files.readAllBytesফাইলের আকারের জন্য উপযুক্ত বাইট অ্যারে বরাদ্দ করা)।


7

আমাকে বলা হয়েছে যে Source.fromFile সমস্যাযুক্ত। ব্যক্তিগতভাবে, সোর্স.ফ্রومফাইলে বড় ফাইল খুলতে আমার সমস্যা হয়েছে এবং জাভা ইনপুট স্ট্রিমগুলি অবলম্বন করতে হয়েছিল।

আরেকটি আকর্ষণীয় সমাধান হ'ল স্কেলাক্স ব্যবহার করা। স্কেলাক্স সাহায্যকারীদের সাথে একটি ফাইল খোলার জন্য ম্যানেজড রিসোর্স ব্যবহার করে একটি লগ ফাইল খোলার জন্য এমন কিছু মন্তব্য করা কোডের একটি উদাহরণ এখানে দেওয়া হয়েছে: http://pastie.org/pastes/420714


6

স্কেল.আইও-তে getLines () ব্যবহার করে সোর্স লাইন টার্মিনেটরগুলির জন্য কোন অক্ষর ব্যবহার করা হয়েছিল তা বাতিল করে (\ n, \ r, \ r \ n, ইত্যাদি)

নিম্নলিখিতগুলিতে এটি চরিত্রের জন্য চরিত্রটি সংরক্ষণ করা উচিত এবং অতিরিক্ত স্ট্রিং কনকেন্টেশন (পারফরম্যান্স সমস্যা) করে না:

def fileToString(file: File, encoding: String) = {
  val inStream = new FileInputStream(file)
  val outStream = new ByteArrayOutputStream
  try {
    var reading = true
    while ( reading ) {
      inStream.read() match {
        case -1 => reading = false
        case c => outStream.write(c)
      }
    }
    outStream.flush()
  }
  finally {
    inStream.close()
  }
  new String(outStream.toByteArray(), encoding)
}

6

আরও একটি: https://github.com/pathikrit/better-files#streams-and-codecs

সামগ্রীগুলিকে মেমরিতে লোড না করে কোনও ফাইল স্লাপ করার বিভিন্ন উপায়:

val bytes  : Iterator[Byte]            = file.bytes
val chars  : Iterator[Char]            = file.chars
val lines  : Iterator[String]          = file.lines
val source : scala.io.BufferedSource   = file.content 

আপনি যে কোনও কিছু পড়তে / লিখতে পারেন তার জন্য আপনার নিজের কোডেকও সরবরাহ করতে পারেন (এটি যদি আপনি সরবরাহ না করেন তবে এটি scala.io.Codec.default ধরে নেয়):

val content: String = file.contentAsString  // default codec
// custom codec:
import scala.io.Codec
file.contentAsString(Codec.ISO8859)
//or
import scala.io.Codec.string2codec
file.write("hello world")(codec = "US-ASCII")

5

জাভাতে যেমন কমন্সআইও লাইব্রেরি ব্যবহার করা হয়েছে:

FileUtils.readFileToString(file, StandardCharsets.UTF_8)

এছাড়াও, এখানে অনেক উত্তর চারসেটকে ভুলে যায়। এটি সর্বদা স্পষ্টভাবে সরবরাহ করা ভাল, বা এটি একদিন আঘাত হানে।


4

কোনও ফাইল খোলার এবং পড়ার রুবি সিনট্যাক্স (এবং শব্দার্থবিজ্ঞান বোঝাতে) অনুকরণ করার জন্য এই অন্তর্নিহিত শ্রেণি (স্কেলা ২.১০ এবং উচ্চতর) বিবেচনা করুন,

import java.io.File

def open(filename: String) = new File(filename)

implicit class RichFile(val file: File) extends AnyVal {
  def read = io.Source.fromFile(file).getLines.mkString("\n")
}

এভাবে,

open("file.txt").read

3

কয়েক জন ব্যক্তি হিসাবে scala.io.S Source উল্লেখ করেছেন সংযোগ ফাঁসের কারণে এড়ানো ভাল।

নতুন ইনকিউবেটর প্রকল্পটি (যেমন স্কাল-আইও) সংহত না হওয়া পর্যন্ত সম্ভবত কমলস-আইওর মতো স্কেলাক্স এবং খাঁটি জাভা লিবগুলি সর্বোত্তম বিকল্প।


3

আপনি ফাইল পড়তে এবং প্রক্রিয়া করতে স্কেলা আইও থেকে পাথটি ব্যবহার করতে পারেন।

import scalax.file.Path

এখন আপনি এটি ব্যবহার করে ফাইলের পাথ পেতে পারেন: -

val filePath = Path("path_of_file_to_b_read", '/')
val lines = file.lines(includeTerminator = true)

আপনি টার্মিনেটরগুলিও অন্তর্ভুক্ত করতে পারেন তবে ডিফল্টরূপে এটি মিথ্যাতে সেট করা থাকে ..


3

দ্রুত সামগ্রিক পড়ার / কোনও (বড়) ফাইল আপলোড করার জন্য, bufferSize( Source.DefaultBufSizeসেট করা 2048) এর আকার বাড়ানোর কথা বিবেচনা করুন, উদাহরণস্বরূপ,

val file = new java.io.File("myFilename")
io.Source.fromFile(file, bufferSize = Source.DefaultBufSize * 2)

নোট উত্স.স্কালা । আরও আলোচনার জন্য স্কেলা দ্রুত পাঠ্য ফাইলটি পড়ুন এবং মেমরিতে আপলোড করুন


3

আপনার প্রতিটি একক লাইন পার্স করার দরকার নেই এবং তারপরে সেগুলি আবার যুক্ত করুন ...

Source.fromFile(path)(Codec.UTF8).mkString

আমি এটি ব্যবহার করতে পছন্দ করি:

import scala.io.{BufferedSource, Codec, Source}
import scala.util.Try

def readFileUtf8(path: String): Try[String] = Try {
  val source: BufferedSource = Source.fromFile(path)(Codec.UTF8)
  val content = source.mkString
  source.close()
  content
}

আপনার স্ট্রিমটি বন্ধ করা উচিত - যদি ত্রুটি দেখা দেয়val content = source.mkString
Andrzej Jozwik

+1 এর জন্য Codec। আমি পরীক্ষাটি ব্যর্থ হয়েছি sbt testকারণ এটি সেট করতে পারছে না, যখন ইন্টেলিজের পরীক্ষা কমান্ড সমস্ত পরীক্ষায় পাস করেছে। আর আপনি ব্যবহার করতে পারেন def usingথেকে এই
মিখাইল Ionkin

3

যদি আপনি কোনও তৃতীয় পক্ষের নির্ভরতা আপত্তি না করেন তবে আপনার আমার ওএস-লিব লাইব্রেরিটি ব্যবহার করা উচিত । এটি ফাইলগুলি পড়া / লেখার এবং ফাইল সিস্টেমের সাথে কাজ করা খুব সুবিধাজনক করে তোলে:

// Make sure working directory exists and is empty
val wd = os.pwd/"out"/"splash"
os.remove.all(wd)
os.makeDir.all(wd)

// Read/write files
os.write(wd/"file.txt", "hello")
os.read(wd/"file.txt") ==> "hello"

// Perform filesystem operations
os.copy(wd/"file.txt", wd/"copied.txt")
os.list(wd) ==> Seq(wd/"copied.txt", wd/"file.txt")

এক-লাইন সাহায্যকারী সঙ্গে বাইট পড়া , খন্ডে পড়া , লাইন পড়া , এবং অন্যান্য অনেক দরকারী / সাধারণ অপারেশন


2

সুস্পষ্ট প্রশ্নটি হ'ল "আপনি কেন পুরো ফাইলটিতে পড়তে চান?" আপনার ফাইলগুলি খুব বড় হয়ে গেলে এটি স্পষ্টতই কোনও স্কেলেযোগ্য সমাধান নয়। scala.io.Sourceআপনি একটি ব্যাক দেয় Iterator[String]থেকেgetLines পদ্ধতি, যা খুবই দরকারী এবং সংক্ষিপ্ত হয়।

এটা তোলে অন্তর্নিহিত জাভা আই ইউটিলিটি ব্যবহার করে একটি রূপান্তর করতে একটি অন্তর্নিহিত রূপান্তর নিয়ে আসা একটি কাজের অনেক না File, একটি Readerবা একটি InputStreamএকটি থেকে String। আমি মনে করি স্কেলাবিলিটির অভাবের অর্থ হ'ল মানক এপিআইতে এটি যুক্ত না করা তারা সঠিক।


12
সিরিয়াসলি? আপনি নিয়মিতভাবে কতগুলি ফাইল পড়েন যা মেমরির সাথে খাপ খায় এমন সমস্যা আছে? আমি যে সকল প্রোগ্রামের সাথে কাজ করেছি তার সিংহভাগ ফাইলগুলি মেমরির সাথে খাপ খায় এমন সহজেই ছোট। স্পষ্টতই, বড় ডেটা ফাইলগুলি ব্যতিক্রম, এবং আপনি সেগুলি পড়তে / লিখতে যাচ্ছেন সে অনুযায়ী আপনার সেই প্রোগ্রামটি অনুধাবন করা উচিত program
ক্রিস্টোফার

8
অক্সবো_লাক্স, আমি একমত নই ছোট ফাইল সম্পর্কিত অনেকগুলি পরিস্থিতি রয়েছে যার আকার ভবিষ্যতে বাড়বে না not
ব্রেন্ডন ওকনোর

4
আমি সম্মত হই যে এগুলি ব্যতিক্রম - তবে আমি মনে করি এই কারণেই কোনও পঠন-সম্পূর্ণ-ফাইল-ইন-মেমরি জেডিকে বা স্কালা এসডিকে হয় না। আপনার নিজের লেখার জন্য এটি একটি 3 লাইনের ইউটিলিটি পদ্ধতি: এটির উপরে
উঠুন

1

প্রতিটি লাইন মুদ্রণ করুন, যেমন জাভা বাফারডিডার ব্যবহার করুন ervy লাইনটি পড়ুন এবং এটি মুদ্রণ করুন:

scala.io.Source.fromFile("test.txt" ).foreach{  print  }

সমতুল্য:

scala.io.Source.fromFile("test.txt" ).foreach( x => print(x))

0
import scala.io.source
object ReadLine{
def main(args:Array[String]){
if (args.length>0){
for (line <- Source.fromLine(args(0)).getLine())
println(line)
}
}

যুক্তিগুলিতে আপনি ফাইলের পথ দিতে পারেন এবং এটি সমস্ত লাইনে ফিরে আসবে


3
এই উত্তরটি কী দেয় যা অন্য উত্তরগুলি না দেয়?
jwvh

অন্য উত্তরগুলি দেখেনি ... কেবল ভেবেছিলাম আমি এখানে পোস্ট করে অবদান রাখতে পারি ... আশা করি এতে কারও ক্ষতি হবে না :)
অপুর

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