fputcsv creates one more space with space - php

I have below code in my script.
$file= fopen("./test.csv","x+");
$proj_lists="name,age,address,city name,country name\n";
fputcsv($file,explode(',',$proj_lists),',',' ');
fclose($file);
It creates a csv file with the given values.
My problem here is it creates extra space with double word.
Example "country name" is written as "country name"(2 spaces in this word).
How to resolve this.

My problem here is it creates extra space with double word
That's because you chose to use a space as the string enclosure character (4th argument, default value is a double quote). Here's the first line of the output:
name,age,address, city name , country name
^ ^^ ^ ^ ^^
e ee e e ee
Where e is the enclosure, and ee is the escaped enclosure, which is the escape character followed by the enclosure character (which happens to be part of the data you're trying to output).
It's best to simply use the defaults that come with fputcsv; that is, call the function with only two arguments.
fputcsv($file, explode(',', $proj_lists));
Which will output what most spreadsheet applications can read:
name,age,address,"city""name","country name
"

Actually you need to work with fputs() like below:-
<?php
$file= fopen("./test.csv","x+");
$proj_lists=explode(',',"name,age,address,city name,country name");
fputs($file,implode($proj_lists, ','));
fclose($file);
?>
Output:- name,age,address,city name,country name

Related

json_encode() character 127 ASCII

Consider the following code:
$str = '';
for ($i=0x0; $i<=0x7f; $i++) {
$str .= chr($i);
}
echo json_encode($str);
The result is:
"\u0000\u0001\u0002\u0003\u0004\u0005\u0006\u0007\b\t\n\u000b\f\r\u000e\u000f\u0010\u0011\u0012\u0013\u0014\u0015\u0016\u0017\u0018\u0019\u001a\u001b\u001c\u001d\u001e\u001f !\"#$%&'()*+,-.\/0123456789:;<=>?#ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~"
There are all but one ASCII characters (the last one): 127 (0x7f).
Is there a way to show that character? (for instance: "\u007f")
Delete (DEL) is a control character in the ASCII character set with the coding 0x7f or 127 decimal. This character is saved as ASCII in the JSON string. This character can be made visible by outputting the JSON string in hexadecimal format.
$jsonStr = json_encode(chr(0x7f));
echo bin2hex($jsonStr); //227f22
22 is the encoding for a double quotation mark ("). echo is not suitable for checking what is in a string. There are always misunderstandings. Control characters (including DEL) are only displayed as spaces in the browser. If you look closely at the result of your code example, you will see the space at the end.
I am not sure, but I think this is what you are searching for:
U+007F
Also see this answer: Why no symbols defined for ascii values from 127 to 159

Unique regex for name validation

I want to check is the name valid with regex PHP, but i need a unique regex that allows:
Letters (upper and lowercase)
Spaces (max 2)
But there can't be a space after space..
For example:
Name -> Dennis Unge Shishic (valid)
Name -> Denis(space)(space) (not valid)
Hope you guys understand me, thank you :)
First, it's worth mentioning that having such restrictive rules for the names of persons is a very bad idea. However, if you must, a simple character class like this will limit you to just uppercase and lowercase English letters:
[A-Za-z]
To match one or more, you need to add a + after it. So, this will match the first part of the name:
[A-Za-z]+
To capture a second name, you just need to do the same thing preceded by a space, so something like this will capture two names:
[A-Za-z]+ [A-Za-z]+
To make the second name optional, you need to surround it by parentheses and add a ? after it, like this:
[A-Za-z]+( [A-Za-z]+)?
And to add a third name, you just need to do it again:
[A-Za-z]+( [A-Za-z]+)? [A-Za-z]+
Or, you could specify that the latter names can repeat between 1 and 2 times, like this:
[A-Za-z]+( [A-Za-z]+){1,2}
To make the resulting code easy to understand and maintain, you could use two Regex. One checking (by requiring it to be true) that only the allowed characters are used ^[a-zA-Z ]+$ and then another one, checking (by requiring it to be false) that there are no two (or more) adjacent spaces ( ){2,}
Try following working code:
Change input to whatever you want to test and see correct validation result printed
<?php
$input_line = "Abhishek Gupta";
preg_match("/[a-zA-Z ]+/", $input_line, $nameMatch);
preg_match("/\s{2,}/", $input_line, $multiSpace);
var_dump($nameMatch);
var_dump($multiSpace);
if(count($nameMatch)>0){
if(count($multiSpace)>0){
echo "Invalid Name Multispace";
}
else{
echo "Valid Name";
}
}
else{
echo "Invalid Name";
}
?>
A regex for one to three words consisting of only Unicode letters in PHP looks like
/^\p{L}+(?:\h\p{L}+){1,2}\z/u
Description:
^ - string start
\p{L}+ - one or more Unicode letters
(?:\h\p{L}+){1,2} - one or two sequences of a horizontal whitespace followed with one or more Unicode letters
\z - end of string, even disallowing trailing newline that a dollar anchor allows.

PHP replace last x character in console

I want to replace last x character from console output.
I can remove complete line by using \r.
But is there a way to just remove last x character from console output ?
In PHP:
To print a backspace character, use 0x08. BUT, there's a problem. If you follow that by a newline "\n" (which you normally would) then the cursor is moved back to EOL, and the characters are exposed again. Good news is that if you follow the 0x08 with the same number of spaces, it works fine. For example, to remove the last two characters:
<?php
print "Hello";
printf("%c%c",0x08,0x08);
print " \n";
?>
Which prints Hel. Note the use of printf() with %c to use an integer (0x08) as a character.
For a generic way to remove x number of characters:
<?php
$x = 4;
$str = "Those who are about to die salute you";
$hacky = str_repeat(chr(0x08),$x).str_repeat(" ",$x);
print "$str$hacky\n";
?>
which prints Those who are about to die salute. Note the use of chr(0x08) here, which returns the character at position 8 in the character set.
You could use the cut command.

Separate (ir)regular expression

I have a string:
A12B34C10G34LongerLongerEven LongerA57
Is there any way to separate the above using regular expressions to the form of:
A12,B34,C10,G34,Longer,Longer,Even Longer,A57
So, separated by commas. I would be grateful for any help. Thanks.
This gives what you need:
<?php
$str = "A12B34C10G34LongerLongerEven LongerA57";
echo preg_replace('/([^\s])([A-Z])/', '\1,\2', $str), "\n";
// OUTPUT: A12,B34,C10,G34,Longer,Longer,Even Longer,A57
preg_replace ('/\B([A-Z])/',',$1',$string);
Inserts a comma before any capital letter that is not on a word boundary.
My assumption is that the input data can consist of capital letters followed by numbers and capitalized words that may or may not be separated by spaces.
import re
ss = ' \tA12B34C10#G34LongerVery LongerEven LongerA57 \n'
print '%r\n%r\n\n%r' %\
(
#good 1
re.sub('(?<=\S)(?=[A-Z])', ',', ss),
#good 2
','.join(
re.findall('(\s*[A-Z].+?\s*)(?=(?<=\S)[A-Z]|\s*\Z)',ss)
),
#bad (written at first)
','.join(
re.findall('(?<!\s)([A-Z].+?)(?<!\s)(?![^A-Z])',ss)
)
)
result
' \tA12,B34,C10#,G34,Longer,Very Longer,Even Longer,A57 \n'
' \tA12,B34,C10#,G34,Longer,Very Longer,Even Longer,A57 \n'
'B34,C10#,G34,Longer,Very Longer,Even Longer'
.
The first solution is as close to the idea (inserting a comma) as possible.
(?<=\S) is mandatory in this solution because each comma must be inserted between characters (correction from DJV)
(?<!\s) would match the beginning of string and a comma would be prepended at the very first position.
.
In a first writing, I had written second solution as
# bad
','.join(re.findall( '(?<!\s)([A-Z].+?)(?<!\s)(?![^A-Z])', ss) )
or
# bad
``','.join(re.findall( '(?<!\s)([A-Z].+?)(?<!\s)(?=[A-Z]|\Z)', ss) )``
where
(?![^A-Z]) or (?=[A-Z]|\Z) were to take account of the end of the string as a possible end of matching portion.
Then
I realized that if whitespaces are at the beginning or the end of the string, there are problems. The above code shows which ones.
To prevent these problems, the solution is the good solution number 2. But it's a complicated one harder to get, so the good solution number 1 is evidently my prefered one.
Try this :
$in = 'A12B34C10G34LongerLongerEven LongerA57';
$output = trim(preg_replace('/([^\s])([A-Z])/', "$1,$2", $in),",");
echo $output;
output : A12,B34,C10,G34,Longer,Longer,Even Longer,A57
Assuming you want to add a ',' in front of each upper case character that is not preceded by a space, here is simple Python regex + sub way of doing it.
string = 'A12B34C10G34LongerLongerEven LongerA57'
re.sub(r'(?<=[^ ])([A-Z])', lambda x: ',' + x.group(0), string)
outputs:
'A12,B34,C10,G34,Longer,Longer,Even Longer,A57'
The regex makes a lookbehind to check for a non-space and the match is an upper character. Then this upper char is prepended a ','.
You could use this assuming you won't get a comma anywhere in $in
explode(",", preg_replace('/([^\s])([A-Z]+)/', "$1,$2", $in);
I don't really know python, but the base regex is the same.

PHP fgetcsv() delimiter

Regarding to fgetcsv() documentation, there are some parameteres inside fgetcsv() function: Handle, length, delimiter, enclosure, and escape.
Now, I have 2 questions:
What does enclosure do exactly?
I have a csv file with 5 columns per line. Imagine it something like this: 1,2,3,4,5
So indexes are from 0 to 4. But whenever I want to get date from index 4, an empty value returns. Unless I put a comma after it (by filling an extra column after it that makes the contents like this: 1,2,3,4,5,6 ). How can I solve this issue ? It seems that there is some problem because of missing comma after the last item in each row of csv file!
1. The enclosure parameter is the character the encapsulates the data for a specific field, or "index". By default, the parameter is a ", which means that you can "enclose" strings in " characters.
Example:
1,2,"this is three",4
2. Per a comment, you're calling fgetcsv($handle, 10000, ','). It's possible, maybe, that the line(s) you're reading are longer than 10000 characters. Try changing the length to 0, which will be "no limit" and see if that helps. Another solution would be to try wrapping the column's value in double-quotes.
Enclosure is the character enclosing the field. It is an extra delimiter, of a sort.
For example hello,world has a comma as field delimiter, and has no text delimiter, while "hello","world" has a quote sign as text delimiter. Some systems employ delimited and undelimited values to indicate text and numeric fields, respectively (I believe Microsoft Excel does). This allows a field to contain the field delimiter in its value:
"Hello,world","Second Field","Third, and last, field".
Some other systems only enclose values containing the field delimiter, or values containing whitespace, which means that on those systems an undelimited value is not necessarily numeric.
If you have a "trivial" case - undelimited values, without escaped field-delimiters inside values (i.e., no 'A,firstpartB\,secondpartB,C' stuff) - you might skip CSV conversion altogether and run
$line = fgets($file, MAX_EXPECTED_LINE_LEN);
// This splits ' A, B, C ' into 'A', ' B' and ' C' (note spaces)
$row = explode(',', trim($line)); // other delimiters can be used
or
// Consider " , ", "," and ", " as the same delimiter
// i.e. ' Alpha , Beta , Gamma ' gets split into 'Alpha', 'Beta' and 'Gamma'
$row = preg_split('#\\s*,\\s*#', trim($line));
I cannot seem to reproduce the problem you are experiencing; could it be related to a different encoding of line endings (i.e., CRLF instead of LF)?
In a pinch, you can divide fgetcsv in the two components fgets and str_getcsv(), manipulating the line between the calls (with trim, or if the worse comes to the worst, by appending the missing comma).
It works to me on this way:
while ($row = $stmt -> fecht()){
echo "\"";
echo $row['email'];
echo "\"";
// Export every row to a file
$arr = array(',');
fputcsv($data, $arr, ";", '"' );
}

Categories