Skip to content

Commit 004cf49

Browse files
committed
CSV.generate_line: use the encoding of the first non ASCII field as the expected encoding
See also: ruby/stringio#13 (comment)
1 parent 8812c58 commit 004cf49

File tree

2 files changed

+26
-2
lines changed

2 files changed

+26
-2
lines changed

lib/csv.rb

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1289,8 +1289,20 @@ def generate_line(row, **options)
12891289
str = +""
12901290
if options[:encoding]
12911291
str.force_encoding(options[:encoding])
1292-
elsif field = row.find {|f| f.is_a?(String)}
1293-
str.force_encoding(field.encoding)
1292+
else
1293+
fallback_encoding = nil
1294+
output_encoding = nil
1295+
row.each do |field|
1296+
next unless field.is_a?(String)
1297+
fallback_encoding ||= field.encoding
1298+
next if field.ascii_only?
1299+
output_encoding = field.encoding
1300+
break
1301+
end
1302+
output_encoding ||= fallback_encoding
1303+
if output_encoding
1304+
str.force_encoding(output_encoding)
1305+
end
12941306
end
12951307
(new(str, **options) << row).string
12961308
end

test/csv/test_encodings.rb

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,18 @@ def test_encoding_is_upgraded_for_ascii_content_during_writing_as_needed
242242
assert_equal("UTF-8", data.to_csv.encoding.name)
243243
end
244244

245+
def test_encoding_is_not_upgraded_for_non_ascii_content_during_writing_as_needed
246+
data = ["\u00c0".encode("ISO-8859-1"), "\u3042"]
247+
assert_equal([
248+
"ISO-8859-1",
249+
"UTF-8",
250+
],
251+
data.collect {|field| field.encoding.name})
252+
assert_raise(Encoding::CompatibilityError) do
253+
data.to_csv
254+
end
255+
end
256+
245257
def test_explicit_encoding
246258
bug9766 = '[ruby-core:62113] [Bug #9766]'
247259
s = CSV.generate(encoding: "Windows-31J") do |csv|

0 commit comments

Comments
 (0)