Out-File
ইউটিএফ -8 ব্যবহার করার সময় বিওএমকে জোর করে বলে মনে হচ্ছে:
$MyFile = Get-Content $MyPath
$MyFile | Out-File -Encoding "UTF8" $MyPath
আমি কীভাবে ইউটিএফ -8 এ বিদ্যুৎ ব্যবহার না করে কোনও বিওএম ব্যবহার করব?
Out-File
ইউটিএফ -8 ব্যবহার করার সময় বিওএমকে জোর করে বলে মনে হচ্ছে:
$MyFile = Get-Content $MyPath
$MyFile | Out-File -Encoding "UTF8" $MyPath
আমি কীভাবে ইউটিএফ -8 এ বিদ্যুৎ ব্যবহার না করে কোনও বিওএম ব্যবহার করব?
উত্তর:
.NET এর UTF8Encoding
ক্লাস ব্যবহার $False
করা এবং কনস্ট্রাক্টরের কাছে যাওয়ার কাজটি মনে হচ্ছে:
$MyRawString = Get-Content -Raw $MyPath
$Utf8NoBomEncoding = New-Object System.Text.UTF8Encoding $False
[System.IO.File]::WriteAllLines($MyPath, $MyRawString, $Utf8NoBomEncoding)
[System.IO.File]::WriteAllLines($MyPath, $MyFile)
যথেষ্ট। এইWriteAllLines
ওভারলোডটি বিওএম ছাড়াই ইউটিএফ 8 লিখেছে।
WriteAllLines
প্রয়োজন বলে মনে হচ্ছে$MyPath
পরম হতে হবে ।
WriteAllLines
থেকে বর্তমান ডিরেক্টরিটি পেয়েছে [System.Environment]::CurrentDirectory
। আপনি যদি পাওয়ারশেলটি ওপেন করেন এবং তারপরে আপনার বর্তমান ডিরেক্টরিটি (ব্যবহার করে cd
বা Set-Location
) পরিবর্তন করেন তবে পরিবর্তন [System.Environment]::CurrentDirectory
হবে না এবং ফাইলটি ভুল ডিরেক্টরিতে থাকবে। আপনি এটিকে ঘিরে কাজ করতে পারেন [System.Environment]::CurrentDirectory = (Get-Location).Path
।
সঠিক এখন হিসাবে উপায় একটি সমাধান @Roman Kuzmin দ্বারা বাঞ্ছনীয় ব্যবহার করা মন্তব্যে @M করতে। ডডলে উত্তর :
[IO.File]::WriteAllLines($filename, $content)
(আমি অপ্রয়োজনীয় System
নেমস্পেসের স্পেসিফিকেশন কেটে এটিকে কিছুটা ছোট করে দিয়েছি - এটি ডিফল্টরূপে স্বয়ংক্রিয়ভাবে প্রতিস্থাপন করা হবে))
[IO.File]::WriteAllLines(($filename | Resolve-Path), $content)
আমি অনুভব করেছি যে এটি ইউটিএফ হবে না, তবে আমি সবেমাত্র একটি খুব সহজ সমাধান পেয়েছি যা কাজ করে বলে মনে হচ্ছে ...
Get-Content path/to/file.ext | out-file -encoding ASCII targetFile.ext
আমার জন্য ফলাফল উত্স বিন্যাস নির্বিশেষে বোম ফাইল ছাড়াই একটি utf-8 এ ফলাফল।
-encoding utf8
আমার প্রয়োজনের জন্য ব্যতীত এটি আমার পক্ষে কাজ করেছিল ।
-Encoding ASCII
বিওএম সমস্যা এড়ায়, তবে আপনি কেবল 7 বিট ASCII অক্ষর পাবেন । প্রদত্ত যে ASCII হল UTF-8 এর একটি উপসেট, ফলস্বরূপ ফাইলটি প্রযুক্তিগতভাবে একটি বৈধ UTF-8 ফাইলও, তবে আপনার ইনপুটটিতে সমস্ত অ-ASCII অক্ষরগুলি আক্ষরিক ?
অক্ষরে রূপান্তরিত হবে ।
-encoding utf8
এখনও ইউটিএফ -8 কে একটি বিওএম দিয়ে আউটপুট করি। :(
দ্রষ্টব্য: এই উত্তরটি উইন্ডোজ পাওয়ারশেলের ক্ষেত্রে প্রযোজ্য ; বিপরীতে, ক্রস প্ল্যাটফর্ম পাওয়ারশেল কোর সংস্করণে (v6 +), বিওএম ছাড়াই ইউটিএফ -8 হ'ল সমস্ত সেমিডলেট জুড়েই ডিফল্ট এনকোডিং ।
অন্য কথায়: আপনি যদি পাওয়ারশেল [কোর] সংস্করণ 6 বা ততোধিক ব্যবহার করে থাকেন তবে আপনি বিওএম-কম ইউটিএফ -8 ফাইল ডিফল্টরূপে পাবেন (যা আপনি স্পষ্টভাবে -Encoding utf8
/ / এর সাথে অনুরোধও -Encoding utf8NoBOM
করতে পারেন, যেখানে আপনি -বিওএম এনকোডিং সহ পাবেন )।-utf8BOM
পূরক এম ডুডলির নিজস্ব সহজ এবং বাস্তববাদী উত্তরকে (এবং ফরনিভের এর আরও সংক্ষিপ্ত সংশোধন) ):
সুবিধার জন্য, এখানে উন্নত ফাংশন Out-FileUtf8NoBom
, একটি পাইপলাইন-ভিত্তিক বিকল্প যা নকল করেOut-File
, যার অর্থ:
Out-File
পাইপলাইনের মতো ব্যবহার করতে পারেন ।Out-File
।উদাহরণ:
(Get-Content $MyPath) | Out-FileUtf8NoBom $MyPath
কীভাবে (Get-Content $MyPath)
বদ্ধ রয়েছে তা নোট করুন (...)
, যা পাইপলাইনের মাধ্যমে ফলাফল পাঠানোর আগে পুরো ফাইলটি খোলার, পুরোপুরি পড়ার এবং বন্ধ করার বিষয়টি নিশ্চিত করে। একই ফাইলটিতে আবার লিখতে সক্ষম হওয়ার জন্য এটি প্রয়োজনীয় (এটি আপডেট করুন) জায়গায় )।
সাধারণত, যদিও এই কৌশলটি 2 কারণে যুক্তিযুক্ত নয়: (ক) পুরো ফাইলটি অবশ্যই মেমরির সাথে মাপসই করা উচিত এবং (খ) কমান্ডটি বাধা দিলে ডেটা নষ্ট হবে।
স্মৃতি ব্যবহারের জন্য একটি নোট :
উত্সের কোডOut-FileUtf8NoBom
( এমআইটি-লাইসেন্সযুক্ত গিস্ট হিসাবেও উপলব্ধ ):
<#
.SYNOPSIS
Outputs to a UTF-8-encoded file *without a BOM* (byte-order mark).
.DESCRIPTION
Mimics the most important aspects of Out-File:
* Input objects are sent to Out-String first.
* -Append allows you to append to an existing file, -NoClobber prevents
overwriting of an existing file.
* -Width allows you to specify the line width for the text representations
of input objects that aren't strings.
However, it is not a complete implementation of all Out-String parameters:
* Only a literal output path is supported, and only as a parameter.
* -Force is not supported.
Caveat: *All* pipeline input is buffered before writing output starts,
but the string representations are generated and written to the target
file one by one.
.NOTES
The raison d'être for this advanced function is that, as of PowerShell v5,
Out-File still lacks the ability to write UTF-8 files without a BOM:
using -Encoding UTF8 invariably prepends a BOM.
#>
function Out-FileUtf8NoBom {
[CmdletBinding()]
param(
[Parameter(Mandatory, Position=0)] [string] $LiteralPath,
[switch] $Append,
[switch] $NoClobber,
[AllowNull()] [int] $Width,
[Parameter(ValueFromPipeline)] $InputObject
)
#requires -version 3
# Make sure that the .NET framework sees the same working dir. as PS
# and resolve the input path to a full path.
[System.IO.Directory]::SetCurrentDirectory($PWD.ProviderPath) # Caveat: Older .NET Core versions don't support [Environment]::CurrentDirectory
$LiteralPath = [IO.Path]::GetFullPath($LiteralPath)
# If -NoClobber was specified, throw an exception if the target file already
# exists.
if ($NoClobber -and (Test-Path $LiteralPath)) {
Throw [IO.IOException] "The file '$LiteralPath' already exists."
}
# Create a StreamWriter object.
# Note that we take advantage of the fact that the StreamWriter class by default:
# - uses UTF-8 encoding
# - without a BOM.
$sw = New-Object IO.StreamWriter $LiteralPath, $Append
$htOutStringArgs = @{}
if ($Width) {
$htOutStringArgs += @{ Width = $Width }
}
# Note: By not using begin / process / end blocks, we're effectively running
# in the end block, which means that all pipeline input has already
# been collected in automatic variable $Input.
# We must use this approach, because using | Out-String individually
# in each iteration of a process block would format each input object
# with an indvidual header.
try {
$Input | Out-String -Stream @htOutStringArgs | % { $sw.WriteLine($_) }
} finally {
$sw.Dispose()
}
}
সংস্করণ from থেকে শুরু করে পাওয়ারশেল সেট-সামগ্রী এবং আউট-ফাইলUTF8NoBOM
উভয়ের জন্য এনকোডিং সমর্থন করে এবং এটি ডিফল্ট এনকোডিং হিসাবে ব্যবহার করে।
সুতরাং উপরের উদাহরণে এটি সহজভাবে এর মতো হওয়া উচিত:
$MyFile | Out-File -Encoding UTF8NoBOM $MyPath
$PSVersionTable.PSVersion
Set-Content
পরিবর্তে ব্যবহার করার সময় Out-File
, আপনি এনকোডিং নির্দিষ্ট করতে পারেন Byte
, যা কোনও ফাইলে বাইট অ্যারে লিখতে ব্যবহার করা যেতে পারে। এটি কাস্টম ইউটিএফ 8 এনকোডিংয়ের সাথে সংমিশ্রণে যা বিওএম নির্গত হয় না তা পছন্দসই ফলাফল দেয়:
# This variable can be reused
$utf8 = New-Object System.Text.UTF8Encoding $false
$MyFile = Get-Content $MyPath -Raw
Set-Content -Value $utf8.GetBytes($MyFile) -Encoding Byte -Path $MyPath
ব্যবহার [IO.File]::WriteAllLines()
বা অনুরূপের পার্থক্য হ'ল এটি কেবল প্রকৃত ফাইল পাথই নয়, যে কোনও ধরণের আইটেম এবং পাথের সাথে ভাল কাজ করা উচিত।
এই স্ক্রিপ্টটি বিআওএম ছাড়াই ইউটিএফ -8 এ রূপান্তরিত হবে, সমস্ত .txt ফাইলগুলিকে DIRECTORY1 এ রূপান্তর করবে এবং এটিকে DIRECTORY2 এ আউটপুট দেবে
foreach ($i in ls -name DIRECTORY1\*.txt)
{
$file_content = Get-Content "DIRECTORY1\$i";
[System.IO.File]::WriteAllLines("DIRECTORY2\$i", $file_content);
}
[System.IO.FileInfo] $file = Get-Item -Path $FilePath
$sequenceBOM = New-Object System.Byte[] 3
$reader = $file.OpenRead()
$bytesRead = $reader.Read($sequenceBOM, 0, 3)
$reader.Dispose()
#A UTF-8+BOM string will start with the three following bytes. Hex: 0xEF0xBB0xBF, Decimal: 239 187 191
if ($bytesRead -eq 3 -and $sequenceBOM[0] -eq 239 -and $sequenceBOM[1] -eq 187 -and $sequenceBOM[2] -eq 191)
{
$utf8NoBomEncoding = New-Object System.Text.UTF8Encoding($False)
[System.IO.File]::WriteAllLines($FilePath, (Get-Content $FilePath), $utf8NoBomEncoding)
Write-Host "Remove UTF-8 BOM successfully"
}
Else
{
Write-Warning "Not UTF-8 BOM file"
}
উত্স কীভাবে পাওয়ারশেল ব্যবহার করে কোনও ফাইল থেকে ইউটিএফ 8 বাইট অর্ডার মার্ক (বিওএম) সরাবেন
আপনি যদি ব্যবহার করতে চান তবে আপনার [System.IO.File]::WriteAllLines()
দ্বিতীয় প্যারামিটারটি কাস্ট করা উচিত String[]
(যদি এর ধরণ থাকে $MyFile
তবে Object[]
) এবং এর সাথে নিখুঁত পথও নির্দিষ্ট করতে হবে $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($MyPath)
:
$Utf8NoBomEncoding = New-Object System.Text.UTF8Encoding $False
Get-ChildItem | ConvertTo-Csv | Set-Variable MyFile
[System.IO.File]::WriteAllLines($ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($MyPath), [String[]]$MyFile, $Utf8NoBomEncoding)
আপনি যদি ব্যবহার করতে চান তবে [System.IO.File]::WriteAllText()
মাঝে মাঝে | Out-String |
প্রতিটি লাইনের শেষে স্পষ্ট করে সিআরএলএফ যুক্ত করতে দ্বিতীয় প্যারামিটারটি পাইপ করা উচিত (বিশেষত যখন আপনি এগুলি ব্যবহার করেন ConvertTo-Csv
):
$Utf8NoBomEncoding = New-Object System.Text.UTF8Encoding $False
Get-ChildItem | ConvertTo-Csv | Out-String | Set-Variable tmp
[System.IO.File]::WriteAllText("/absolute/path/to/foobar.csv", $tmp, $Utf8NoBomEncoding)
অথবা আপনি ব্যবহার করতে পারেন [Text.Encoding]::UTF8.GetBytes()
সঙ্গে Set-Content -Encoding Byte
:
$Utf8NoBomEncoding = New-Object System.Text.UTF8Encoding $False
Get-ChildItem | ConvertTo-Csv | Out-String | % { [Text.Encoding]::UTF8.GetBytes($_) } | Set-Content -Encoding Byte -Path "/absolute/path/to/foobar.csv"
দেখুন: বিওএম ছাড়াই ইউটিএফ -8-এ কোনও ফাইলে কনভার্টটো-সিএসভির ফলাফল কীভাবে লিখবেন
$ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($MyPath)
হ'ল Convert-Path $MyPath
; আপনি যদি কোনও পিছনের সিআরএলএফ নিশ্চিত করতে চান তবে কেবল [System.IO.File]::WriteAllLines()
একটি একক ইনপুট স্ট্রিং দিয়েও (কোনও প্রয়োজন নেই Out-String
) ব্যবহার করুন।
আমি যে কৌশলটি ব্যবহার করি তা হ'ল আউট-ফাইল সেন্টিমিডলেট ব্যবহার করে কোনও ASCII ফাইলে আউটপুট পুনর্নির্দেশ করা ।
উদাহরণস্বরূপ, আমি প্রায়শই এসকিউএল স্ক্রিপ্টগুলি চালিত করি যা ওরাকলে এক্সিকিউট করতে অন্য এসকিউএল স্ক্রিপ্ট তৈরি করে। সাধারণ পুনঃনির্দেশের (">") সাথে আউটপুটটি ইউটিএফ -16 এ হবে যা এসকিউএলপ্লাস দ্বারা স্বীকৃত নয়। এটি প্রায় কাজ করতে:
sqlplus -s / as sysdba "@create_sql_script.sql" |
Out-File -FilePath new_script.sql -Encoding ASCII -Force
উত্পন্ন স্ক্রিপ্টটি কোনও ইউনিকোড উদ্বেগ ছাড়াই অন্য এসকিউএলপ্লাস সেশনের মাধ্যমে কার্যকর করা যেতে পারে:
sqlplus / as sysdba "@new_script.sql" |
tee new_script.log
-Encoding ASCII
বিওএম সমস্যা এড়ায়, তবে আপনি অবশ্যই 7-বিট ASCII অক্ষরের জন্য সমর্থন পাবেন । প্রদত্ত যে ASCII হল UTF-8 এর একটি উপসেট, ফলস্বরূপ ফাইলটি প্রযুক্তিগতভাবে একটি বৈধ UTF-8 ফাইলও, তবে আপনার ইনপুটটিতে সমস্ত অ-ASCII অক্ষরগুলি আক্ষরিক ?
অক্ষরে রূপান্তরিত হবে ।
বিওএম ছাড়াই ইউটিএফ -8 এ এক্সটেনশান দ্বারা একাধিক ফাইল পরিবর্তন করুন:
$Utf8NoBomEncoding = New-Object System.Text.UTF8Encoding($False)
foreach($i in ls -recurse -filter "*.java") {
$MyFile = Get-Content $i.fullname
[System.IO.File]::WriteAllLines($i.fullname, $MyFile, $Utf8NoBomEncoding)
}
যে কারণেই হোক না কেন, WriteAllLines
কলগুলি এখনও বিএমএসবিহীন UTF8Encoding
যুক্তি ছাড়াই এবং এটি ছাড়াই আমার জন্য একটি বিএম তৈরি করে। তবে নিম্নলিখিতগুলি আমার পক্ষে কাজ করেছে:
$bytes = gc -Encoding byte BOMthetorpedoes.txt
[IO.File]::WriteAllBytes("$(pwd)\BOMthetorpedoes.txt", $bytes[3..($bytes.length-1)])
এটি কাজ করার জন্য আমাকে ফাইলের পথকে নিখুঁত করতে হয়েছিল। অন্যথায় এটি আমার ডেস্কটপে ফাইলটি লিখেছিল। এছাড়াও, আমি মনে করি এটি কেবল তখনই কাজ করে যদি আপনি জানেন যে আপনার বিওএমটি 3 বাইট। এনকোডিংয়ের উপর ভিত্তি করে প্রদত্ত বিওএম ফর্ম্যাট / দৈর্ঘ্য আশা করা কতটা নির্ভরযোগ্য আমার কোনও ধারণা নেই।
এছাড়াও, লিখিত হিসাবে, এটি সম্ভবত তখনই কাজ করে যদি আপনার ফাইলটি পাওয়ারশেল অ্যারের সাথে ফিট [int32]::MaxValue
করে তবে আমার মেশিনের চেয়ে কিছুটা দৈর্ঘ্যের সীমা কম রয়েছে বলে মনে হয় ।
WriteAllLines
ছাড়া একটি এনকোডিং যুক্তি কখনো BOM লিখেছেন নিজেই , কিন্তু এটা অনুমেয় যে আপনার স্ট্রিং BOM দিয়ে শুরু ঘটেছে চরিত্র ( U+FEFF
উপর কার্যকরভাবে একটি হল UTF-8 BOM নির্মিত লিখিত যা); যেমন: $s = [char] 0xfeff + 'hi'; [io.file]::WriteAllText((Convert-Path t.txt), $s)
( কোনও বিওএম লেখা নেই[char] 0xfeff +
তা দেখতে বাদ দিন )।
[Environment]::CurrentDirectory = $PWD.ProviderPath
, বা আপনার "$(pwd)\..."
পদ্ধতির আরও জেনেরিক বিকল্প হিসাবে (আরও ভাল: "$pwd\..."
এমনকি আরও ভাল: "$($pwd.ProviderPath)\..."
বা (Join-Path $pwd.ProviderPath ...)
), ব্যবহার করুন(Convert-Path BOMthetorpedoes.txt)
U+FEFF
সম্পর্কিত এনকোডিংয়ের বাইট উপস্থাপনা ।
বিওএম ছাড়াই ইউটিএফ 8 পেতে নীচে ব্যবহার করতে পারেন
$MyFile | Out-File -Encoding ASCII
ASCII
ইউটিএফ -8 নয়, তবে এটি বর্তমান এএনএসআই কোডপেজ নয় - আপনি ভাবছেন Default
; ASCII
কোডপয়েন্টস> = 128 আক্ষরিক ?
দৃষ্টান্তে রূপান্তরিত হয়ে সত্যই 7 বিট ASCII এনকোডিং ।
-Encoding ASCII
সত্যই এটি 7-বিট ASCII কেবল তা যাচাই করতে চেষ্টা করুন : 'äb' | out-file ($f = [IO.Path]::GetTempFilename()) -encoding ASCII; '?b' -eq $(Get-Content $f; Remove-Item $f)
- এটিকে ä
একটিতে প্রতিলিপি করা হয়েছে ?
। বিপরীতে, -Encoding Default
("এএনএসআই") এটি সঠিকভাবে সংরক্ষণ করবে।
এটি আমার জন্য কাজ করে ("ইউটিএফ 8" এর পরিবর্তে "ডিফল্ট" ব্যবহার করুন):
$MyFile = Get-Content $MyPath
$MyFile | Out-File -Encoding "Default" $MyPath
ফলাফল বিওএম ছাড়াই এএসসিআইআই।
Default
এনকোডিং, সিস্টেমের বর্তমান ANSI কোড পৃষ্ঠা, যা হল UTF-8 নয় ব্যবহার করবে আমি প্রয়োজন।