Read Text File into an Array

Read text file into an array

Use an ArrayList or an other dynamic datastructure:

BufferedReader abc = new BufferedReader(new FileReader(myfile));
List<String> lines = new ArrayList<String>();

while((String line = abc.readLine()) != null) {
lines.add(line);
System.out.println(data);
}
abc.close();

// If you want to convert to a String[]
String[] data = lines.toArray(new String[]{});

Java read file and store text in an array

Stored as strings:

public class ReadTemps {

public static void main(String[] args) throws IOException {
// TODO code application logic here

// // read KeyWestTemp.txt

// create token1
String token1 = "";

// for-each loop for calculating heat index of May - October

// create Scanner inFile1
Scanner inFile1 = new Scanner(new File("KeyWestTemp.txt")).useDelimiter(",\\s*");

// Original answer used LinkedList, but probably preferable to use ArrayList in most cases
// List<String> temps = new LinkedList<String>();
List<String> temps = new ArrayList<String>();

// while loop
while (inFile1.hasNext()) {
// find next line
token1 = inFile1.next();
temps.add(token1);
}
inFile1.close();

String[] tempsArray = temps.toArray(new String[0]);

for (String s : tempsArray) {
System.out.println(s);
}
}
}

For floats:

import java.io.File;
import java.io.IOException;
import java.util.LinkedList;
import java.util.List;
import java.util.Scanner;

public class ReadTemps {

public static void main(String[] args) throws IOException {
// TODO code application logic here

// // read KeyWestTemp.txt

// create token1

// for-each loop for calculating heat index of May - October

// create Scanner inFile1
Scanner inFile1 = new Scanner(new File("KeyWestTemp.txt")).useDelimiter(",\\s*");


// Original answer used LinkedList, but probably preferable to use ArrayList in most cases
// List<Float> temps = new LinkedList<Float>();
List<Float> temps = new ArrayList<Float>();

// while loop
while (inFile1.hasNext()) {
// find next line
float token1 = inFile1.nextFloat();
temps.add(token1);
}
inFile1.close();

Float[] tempsArray = temps.toArray(new Float[0]);

for (Float s : tempsArray) {
System.out.println(s);
}
}
}

Reading text file into an array in C

You are on the right track. Here is my contribution on the topic:

  1. Open the file (fopen)
  2. Count number of lines (getc and rewind)
  3. Read all lines into array (getline)
  4. Free memory and close file (free and fclose)

Code example:

#include <stdlib.h>
#include <stdio.h>

int main(int argc, char *argv[])
{

// Open File
const char fname[] = "testFile.txt";

FILE *fp = fopen(fname, "r");

if( !fp )
goto error_open_file;
printf("Opened file: %s\n", fname);

// Count Lines
char cr;
size_t lines = 0;

while( cr != EOF ) {
if ( cr == '\n' ) {
lines++;
}
cr = getc(fp);
}
printf("Number of lines: %ld\n", lines);
rewind(fp);

// Read data
{// 'goto' + data[lines] causes error, introduce block as a workaround
char *data[lines];
size_t n;

for (size_t i = 0; i < lines; i++) {
data[i] = NULL;
size_t n = 0;

getline(&data[i], &n, fp);

if ( ferror( fp ) )
goto error_read_file;

}

for (size_t i = 0; i < lines; i++) {
printf("%s", data[i]);
free(data[i]);
}
}

// Close File
fclose(fp);

return 0;

error_read_file:
perror("fopen ");
return 1;

error_open_file:
perror("getline ");
return 2;

}

How do I read in a text file separated by spaces into an array in c++?

I have given 2 solutions to this problem. The below program reads double from input.txt and if there is some invalid entry in the file lets say there is some string then it will skip that string and read the next value and only if that value is valid(double) it will put it into the array as you desire.

Solution 1: Using built in arrays

#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
int main()
{

std::string line;

std::ifstream inFile("input.txt");

//in case of using array, size must be fixed and predetermined
double arr[20] = {0.0}; //you can choose size according to your needs
if(inFile)
{
double i = 0;//this variable will be used to add element into the array
int count = 0;
while(getline(inFile, line, '\n'))
{



std::istringstream s(line);

//take input(from s to i) and then checks stream's eof flag status
while(s >> i || !s.eof()) {
//check if either failbit or badbit is set
if(s.fail())
{
//clear the error state to allow further operations on s
s.clear();
std::string temp;
s >> temp;
continue;
}
else
{

arr[count] = i;
++count;

//break out of the loop so that we don't go out of bounds
if(count >= 20)
{
break;
}
}

}


}
}
else
{
std::cout<<"file could not be read"<<std::endl;
}
inFile.close();

for(double i: arr)
{
std::cout<<"elem: "<<i<<std::endl;
}

return 0;
}

The output of solution 1 can be checked here.

Solution 2: Using std::vector

#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
int main()
{

std::string line;;

std::ifstream inFile("input.txt");

std::vector<double> vec;
if(inFile)
{
double i = 0;//this variable will be used to add element into the vector

while(getline(inFile, line, '\n'))
{



std::istringstream s(line);
//take input(from s to i) and then checks stream's eof flag status
while(s >> i || !s.eof()) {
if(s.fail())
{
//clear the error state to allow further operations on s
s.clear();
std::string temp;
s >> temp;
continue;
}
else
{
vec.push_back(i);
}

}


}
}
else
{
std::cout<<"file could not be read"<<std::endl;
}
inFile.close();

for(double i: vec)
{
std::cout<<"elem: "<<i<<std::endl;
}

return 0;
}

The output of solution 2 can be seen here.

Both of these versions work even if there is an invalid input(like a string) in the input.txt file. As you can see here the input.txt file has strings in between numbers. The program just skips those invalid input and read the next thing. And if that next thing is double, it puts that thing/value into the vector/array.

Important Note

The advantage of using std::vector over built in array(in this case) is that you don't have know the size of the vector beforehand. So it is preferable because you don't know how many integers are there in the input.txt file. std::vector can handle this correctly/dynamically. But when using built in arrays you must know/specify the size of the array beforehand. This in turn means you must know beforehand how many integers are there in the input.txt, which is not practical.

node.js: read a text file into an array. (Each line an item in the array.)

If you can fit the final data into an array then wouldn't you also be able to fit it in a string and split it, as has been suggested?
In any case if you would like to process the file one line at a time you can also try something like this:

var fs = require('fs');

function readLines(input, func) {
var remaining = '';

input.on('data', function(data) {
remaining += data;
var index = remaining.indexOf('\n');
while (index > -1) {
var line = remaining.substring(0, index);
remaining = remaining.substring(index + 1);
func(line);
index = remaining.indexOf('\n');
}
});

input.on('end', function() {
if (remaining.length > 0) {
func(remaining);
}
});
}

function func(data) {
console.log('Line: ' + data);
}

var input = fs.createReadStream('lines.txt');
readLines(input, func);

EDIT: (in response to comment by phopkins) I think (at least in newer versions) substring does not copy data but creates a special SlicedString object (from a quick glance at the v8 source code). In any case here is a modification that avoids the mentioned substring (tested on a file several megabytes worth of "All work and no play makes Jack a dull boy"):

function readLines(input, func) {
var remaining = '';

input.on('data', function(data) {
remaining += data;
var index = remaining.indexOf('\n');
var last = 0;
while (index > -1) {
var line = remaining.substring(last, index);
last = index + 1;
func(line);
index = remaining.indexOf('\n', last);
}

remaining = remaining.substring(last);
});

input.on('end', function() {
if (remaining.length > 0) {
func(remaining);
}
});
}

Getting input from text file and storing into array but text file contains more than 20.000 strings

You requirement is to NOT use any standard container like for example a std::vector or a std::unordered_map.

In this case we need to create a dynamic container by ourself. That is not complicated. And we can use this even for storing strings. So, I will even not use std::string in my example.

I created some demo for you with ~700 lines of code.

We will first define the term "capacity". This is the number of elements that could be stored in the container. It is the currently available space. It has nothing to do, how many elements are really stored in the container.

But there is one and the most important functionality of a dynamic container. It must be able to grow. And this is always necessary, if we want to store add more elements to the container, as its capacity.

So, if we want to add an additional element at the end of the container, and if the number of elements is >= its capacity, then we need to reallocate bigger memory and then copy all the old elements to the new memory space. For such events, we will usually double the capacity. This should prevent frequent reallocations and copying activities.

Let me show you one example for a push_back function, which could be implemented like this:

template <typename T>
void DynamicArray<T>::push_back(const T& d) { // Add a new element at the end
if (numberOfElements >= capacity) { // Check, if capacity of this dynamic array is big enough
capacity *= 2; // Obviously not, we will double the capacity
T* temp = new T[capacity]; // Allocate new and more memory
for (unsigned int k = 0; k < numberOfElements; ++k)
temp[k] = data[k]; // Copy data from old memory to new memory
delete[] data; // Release old memory
data = temp; // And assign newly allocated memory to old pointer
}
data[numberOfElements++] = d; // And finally, store the given data at the end of the container
}

This is a basic approach. I use templates in order to be able to store any type in the dynamic array.

You could get rid of the templates, by deleting all template stuff and replacing "T" with your intended data type.

But, I would not do that. See, how easy we can create a "String" class. We just typedef a dynamic array for chars as "String".

using String = DynamicArray<char>;

will give us basic string functionality. And if we want to have a dynamic array of strings later, we can write:

using StringArray = DynamicArray<String>;

and this gives us a DynamicArray<DynamicArray<char>>. Cool.

For this special classes we can overwrite some operators, which will make the handling and our life even more simple.

Please look in the provided code


And, to be able to use the container in the typical C++ environment, we can add full iterator capability. That makes life even more simple.

This needs really some typing effort, but is not complicated. And, it will make life really simpler.


You also wanted to create a hash map. For counting words.

For that we will create a key/value pair. The key is the String that we defined above and the value will be the frequency counter.

We implement a hash function which should be carefully selected to work with strings, has a high entropy and give good results for the bucket size of the hash map.

The hash map itself is a dynamic container. We will also add iterator functionality to it.


For all this I drafted some 700 lines of code for you. You can take this as an example for your further studies.

It can also be easily enhanced with additional functionality.

But caveat: I did only some basic tests and I even used raw pointers for owned memory. This can be done in a schoolproject to learn some dynamic memory management, but not in reality.

Additionlly. You can replace all this code, by simply using std::string, std::vector and std::unordered_map. Nobody would use such code and reinvent the wheel.

But it may give you some ideas on how to implement similar things.

Because Stackoverlof limits the answer size to 32000 characters, I will put the main part on github.

Please click here.

I will just show you main so that you can see how easy the solution can be used:

int main() {

// Open file and check, if it could be opened
std::ifstream ifs{ "r:\\test.txt" };
if (ifs) {

// Define a dynamic array for strings
StringArray stringArray{};

// Use overwritten extraction operator and read all strings from the file to the dynamic array
ifs >> stringArray;

// Create a dynamic hash map
HashMap hm{};

// Now count the frequency of words
for (const String& s : stringArray)
hm[s]++;

// Put the resulting key/value pairs into a dynamic array
DynamicArray<Item> items(hm.begin(), hm.end());

// Sort in descending order by the frequency
std::sort(items.begin(), items.end(), [](const Item& i1, const Item& i2) { return i1.count > i2.count; });

// SHow resulton screen
for (const auto& [string, count] : items)
std::cout << std::left << std::setw(20) << string << '\t' << count << '\n';
}
else std::cerr << "\n\nError: Could not open source file\n\n";
}


Related Topics



Leave a reply



Submit