I have a CSV file with:
Test1,One line
Test2,"Two lines
Hello"
Test3,One line
As you can see, one of the columns has a value which is separated with a new line.
To parse this CSV file into an array, I run:
$csvArray = array();
$csvData = file_get_contents('file.csv');
$lines = explode(PHP_EOL, $csvData);
foreach ($lines as $line) {
$csvArray[] = str_getcsv($line);
}
// print_r($csvArray);
It works beside one problem. It reads the new line in the value as a new row, which is completely incorrect.
How do I make it so that it properly reads a multi-line value?
Edit: this question focuses on new lines.
$fp = fopen('filecsv', 'r');
$csvArray = array();
while ($row = fgetcsv($fp)) {
$csvArray[] = $row;
}
fclose($fp);
Using explode(PHP_EOL, $csvData) will not correctly split the CSV by its row delimitor. The multi line cell is encapsulated with quotations meaning the row will continue onto new lines until they are closed.
PHP's built in fgetcsv function will correctly read a single row from a file, moving the pointer to the next row in the process. While str_getcsv will only read a single row from a string without considering additional rows (because its a string, not a stream).
Since you have already split the string with explode, your CSV row is broken, so the row will be incomplete.
Related
This is a really odd behavior that I can't explain. I have a CSV file that I'm trying to format. The lines could have trailing ','s that I want to remove.
$lines = explode(PHP_EOL, $csv);
$csv = '';
foreach($lines as $line) {
$csv .= trim($line, ',') . PHP_EOL;
}
The trim is not doing anything and just returning the line back as it is. Just to make sure I copied a line from the csv trim("a,b,c,d,,", ','); which works fine. Can anyone tell me why the above code won't work?
If the CSV file was created on a different operating system, it may use different line breaks than PHP_EOL. So trim any line break characters in addition to commas.
foreach($lines as $line) {
$csv .= trim($line, ",\r\n") . PHP_EOL;
}
Don't manually edit the CSV file. Parse it into an array, then edit the array. Then you can write the modified array back to a CSV file.
You can use fputcsv to write the data to a file, or str_putcsv (a custom function).
$newData = [];
$data = array_map('str_getcsv', $lines); // parse each line as a CSV
foreach ($data as $row) {
$row = array_filter($row); // remove blank values
// for some dumb reason, php has `str_getcsv` but not `str_putcsv`
// so let's use `str_putcsv` from: https://gist.github.com/johanmeiring/2894568
$newData[] = str_putcsv($row);
}
$newData = implode(PHP_EOL, $newData);
I'm using fgets() to pull the first line of a txt file that I made with another program and save it as a string. The problem is that I'd like to assign each word as a different variable.
Here is the first line of my txt file:
1435055708,10.9336,8.2295,11.8359,8.2734,10.8750,8.2148,14.6670,12.9922,
Here is my code:
<?php
$outputFile = fopen("output.txt", "r") or die("Unable to open data log file!");
$firstLine = fgets($outputFile);
echo $firstLine;
?>
This just stores the line as the string $firstLine.
I'm trying to split this line into 9 variables
Timestamp = 1435055708
Channel 0 = 10.9336
Channel 1 = 8.2295
...and so on
If the data structure is always the same in your file you can go like this:
$parts = explode(',', $firstLine);
list($timestamp, $channel0, $channel1, ...) = $parts;
The first line will slice your string into an array (every comma separated value will become a new value in an array).
The second line will take the array values and assign them to your desired variables.
Of course all of this can be joined into a single line:
list($timestamp, $channel0, $channel1, ...) = explode(',', fgets($outputFile));
#MaGnetas solution is correct just an explanation
explode will break the firstline by delimiter ',' and return an zero indexed array which you can use as it is or create a list
$arr = explode(',',$firstLine);
i need to generate random sentences from dictionary. In dictionary is every word at one line, firstly i load this dictionary to array and after it i have a for cycle and randomly pickup some data, but if i wrote it, so it is at one line in browser, but in source code is every word at another line. Then I need to create a set of XML files from search engine and this new lines are indexed as /n/r and in XML source code it has got a symbol
So my question is how i can make a sentence which will be at one line in source code too. Thanks.
Here is piece of my code i donĀ“t have here randomly loading data, i only made it for illustration in for cycle.
$file = fopen("test.txt", "r");
$data = array();
while (($buffer = fgets($file)) !== false) {
$data[] = $buffer;
}
$sentence = '';
for ($i=0;$i<10;$i++){
$sentence = $sentence . $data[$i];
}
Use trim function to filter new line characters.
In your code use:
$data[] = trim($buffer);
I'm trying to delete/edit some portion of text from text file, like if I have 10 lines in my text file then I want to edit 5th line or delete 3rd line without affecting any other line.
Currently what I'm doing
1. open text file and read data in php variable
2. done editing on that variable
3. delete the content of text file.
4. write new content on it
but is there any way to doing that thing without deleting whole content or by just edit those content?
my current code is like this
$file = fopen("users.txt", "a+");
$data = fread($file, filesize("users.txt"));
fclose($file);
$newdata = str_replace($old, $new, $data);
file_put_contents("users.txt", "");
$file = fopen("users.txt", "a+");
fwrite($file, $newdata);
fclose($file);
You could shorten that to:
$data = file_get_contents("users.txt");
$newdata = str_replace($old, $new, $data);
file_put_contents("users.txt", $newdata);
$str = '';
$lines = file("users.txt");
foreach($lines as $line_no=>$line_txt)
{
$line_no += 1; // Start with zero
//check the line number and concatenate the string
if($line_no == 5)
{
// Append the $str with your replaceable text
}
else{
$str .= $line_txt."\n";
}
}
// Then overwrite the $str content to same file
// i.e file_put_contents("users.txt", $str);
I have added solution as per my understanding, Hope it will help!!!
You can work on each line:
$lines = file("users.txt");
foreach($lines as &$line){
//do your stufff
// $line is one line
//
}
$content = implode("", $lines);
//now you can save $content like before
If you've only got 10 lines in your text file, then unless they are very long lines you're changing the amount of physical I/O required to change the contents (disks will only read/write data one physical sector at a time - and the days of 512byte sectors are long gone).
Yes, you can modify a large file by only writing the sectors which have changed - but that requires that you replace the data with something the same size to prevent framing errors (in PHP using fopen with mode c+, fgets/fseek/fwrite/ftell, fclose).
Really the corect answer is to stop storing multivalued data in a text file and use a DBMS (which also solves the concurrency issues).
I have a PHP script that reads the contents of a file and stores it into a variable. I want to split the text stored by the new line entries and then search the array[0] value for a specific value.
That is my idea. Here is my situation.
I have a directory file with specific entries.
Entry1_two_term3_stuff
Entry2_two_term3_stuff
Entry3_two_term3_stuff
This will be stored into a variable. How do I search this for Entry2 and then get the whole line to work with?
If you can, use the file() function to load the file into array, already split by newlines:
$lines = file('filename.txt');
If not, you can use
$lines = explode("\n", $contents);
You might want to use \r\n if you're on Windows and file contains CR characters.
To search the array, use foreach:
foreach ($lines as $ix => $line)
if (strpos ($line, 'string') !== false)
$lines[$ix] = ...new version of line...
In the end, write contents back to some file:
$fp = fopen('file.txt', 'w+');
foreach ($lines as $line)
fputs($fp, $line);
fclose($fp);
You could search the directories with RecursiveDirectoryIterator, and search the files contents individually with preg_match_all