動くコード図鑑技術記事現場の渡り方キャリア論すべての記事About
技術記事

PowerShell の Import-Csv / Export-Csv で業務SEが踏む5つの罠 — 文字コード・区切り・型・改行・BOM

バイブス父さん
現役の業務SE
2026年7月13日10 min read
PowerShell の Import-Csv / Export-Csv で業務SEが踏む5つの罠 — 文字コード・区切り・型・改行・BOM

みなさんこんにちは!ヒロポンです!

PowerShell で CSV を読んだら日本語が全部 ??? に化けてた。Excel で開いたら「0001」が「1」になってた。こういうの、覚えありませんか??

データ移行とか帳票連携で Import-Csv / Export-Csv を触ると、地味な罠を踏みまくります。やっかいなのは、エラーにならないこと。静かにデータがズレる。これが一番こわい。

今回は、PowerShell CSV 読み込みまわりで業務SEがよく踏む罠を、実体験ベースで5つに絞りました。リファレンスとしてブックマークしといてください。

対象は Windows の現場で Import-Csv / Export-Csv を叩く人。コピペで動く最小例も置いときます。

⏱ 5つの罠と対処目安(先に全体像)

細かい話の前に、何にどれだけかかるかだけ先に出します。

# 症状 対処 ⏱ 対処目安
1 -Encoding 未指定 日本語が ? や文字化け -Encoding を必ず明示 5分
2 UTF-8 の BOM 連携先が先頭列を読み損なう BOM なしで書き出す 10分
3 #TYPE 先頭行が #TYPE ... で壊れる -NoTypeInformation 1分
4 全カラムが文字列 数値計算・日付比較がズレる [int] / [datetime] で明示キャスト 5分
5 区切りがカンマ以外 全部が1列に入る -Delimiter を指定 2分

最小の読み書きはこんな感じです。ここに上の5つが乗っかってきます。

# 読み込み
$rows = Import-Csv -Path .\input.csv -Encoding Default

# 書き出し
$rows | Export-Csv -Path .\output.csv -Encoding UTF8 -NoTypeInformation

ではいきます!!

1. -Encoding を指定しないと Shift_JIS が文字化けする

俺が最初にやられたのがこれ。Shift_JIS で作られた業務CSVを何気なく Import-Csv したら、日本語の列が全部文字化け。30分くらい「データ側が壊れてんのか??」って疑って、犯人が文字コードだと気付くまでだいぶ遠回りした。

Import-CsvExport-Csv も、-Encoding を省略すると PowerShell のバージョン依存の既定で読み書きします。ここが地雷。

# Shift_JIS の CSV (Windows の Excel が吐く既定) を読む
$rows = Import-Csv -Path .\sjis.csv -Encoding Default
# ※ Windows PowerShell 5.1 の Default は環境のコードページ (日本語環境なら cp932 = Shift_JIS 相当)

# UTF-8 の CSV を読む
$rows = Import-Csv -Path .\utf8.csv -Encoding UTF8

PowerShell 7 だと既定が UTF-8 寄りに変わる。だから逆に、Shift_JIS を読むときは -Encoding で明示してやらないと化けます。

教訓はシンプル。CSV を読み書きするなら -Encoding は必ず書く。省略して「たまたま動いた」やつは、別環境に持っていった瞬間に必ず化けます。

CSV を AD のユーザー登録あたりに流す時も理屈は同じで、入口の文字コードがズレてると後段が全部おかしくなる(PowerShell で AD バルクユーザー作成 の話とも地続きです)。

2. Export-Csv の UTF-8 が BOM 付きで他システムが読めない

これも一晩持っていかれたやつ。Export-Csv -Encoding UTF8 で吐いた CSV を連携先に食わせたら、「1列目のヘッダーが認識できない」って弾かれる。

犯人は BOM(Byte Order Mark)。Windows PowerShell 5.1 の -Encoding UTF8 は、ファイル先頭に見えない3バイト(EF BB BF)をこっそり付けます。これを知らない連携先だと、先頭列名が Name みたいに化けて読めない。

# PowerShell 7 なら BOM なし UTF-8 が既定。明示するならこう
$rows | Export-Csv -Path .\out.csv -Encoding utf8NoBOM -NoTypeInformation

PowerShell 7 では utf8NoBOM が既定なので、基本そのまま安全。問題は 5.1 で UTF-8 BOM なしを出したいケース。ここは Export-Csv 単体だと素直にいきません。Set-Content[System.Text.UTF8Encoding]::new($false) を使って書き直す、みたいな逃げが要ることがあります。

教訓は、連携用の CSV は「BOM が付いてないか」を必ず確認する。バイナリエディタか、メモ帳の「名前を付けて保存」の文字コード欄で先頭を見れば一発です。

3. 先頭に #TYPE 行が出て連携先が壊れる

これは1分で直る。ただ、知らないと永遠にハマるやつ。

Windows PowerShell 5.1 の Export-Csv は、ファイルの先頭に #TYPE System.Management.Automation.PSCustomObject という行を勝手に付けることがあります。

#TYPE System.Management.Automation.PSCustomObject
"Name","Amount"
"田中","1000"

この #TYPE 行のせいで、連携先が「1行目がヘッダーのはず」と思って読むと、列がまるごとズレる。

対処は -NoTypeInformation を付けるだけ。

$rows | Export-Csv -Path .\out.csv -Encoding UTF8 -NoTypeInformation

PowerShell 7 では #TYPE 行は既定で出ないので、-NoTypeInformation は省略しても平気。とはいえ、5.1 と 7 の両方で動かすスクリプトなら、付けておいて損はない。書き出し系は -NoTypeInformation をテンプレに練り込んでおく、が結論です。

4. 全カラムが文字列として読まれて数値計算がズレる

Import-Csv の地味な罠がこれ。読み込んだ各カラムは、全部 [string]になります。数字に見えても中身は文字列。

だから + 演算子で計算したつもりが、しれっと文字列連結になる。

$rows = Import-Csv -Path .\data.csv

# ❌ Amount は文字列なので、+ は足し算じゃなく文字列連結
$rows[0].Amount + 100        # "1000" + 100 → "1000100"(連結されてしまう)

# ✅ 明示的に [int] へキャストしてから計算する
[int]$rows[0].Amount + 100   # 1100(ちゃんと足せる)

# 集計も先にキャストが安全。Measure-Object は数値文字列なら自動変換するが、
# 1件でも数値じゃない値が混じると "not numeric" で集計が止まる
$total = ($rows | ForEach-Object { [int]$_.Amount } | Measure-Object -Sum).Sum

日付も理屈は同じ。"2026/06/30" は文字列のまま。[datetime]$_.Date でキャストしてやると、いい感じに日付として比較・ソートできます。これをサボって、文字列順のまま月またぎの集計をやると、数字が静かにズレる。一番こわいパターンです。

教訓は、CSV から読んだ数値・日付は、計算前に必ずキャストする[int] / [decimal] / [datetime] を1回挟むだけで事故が消えます。

5. 区切りがカンマ以外(タブ・セミコロン)で1列になる

最後はあっさり。TSV(タブ区切り)やセミコロン区切りの CSV を、そのまま Import-Csv すると全部が1列に入って「ん?列が取れない??」ってなります。

# タブ区切り (TSV) を読む
$rows = Import-Csv -Path .\data.tsv -Delimiter "`t" -Encoding Default

# セミコロン区切り (一部の地域設定の Excel が吐く) を読む
$rows = Import-Csv -Path .\data.csv -Delimiter ";" -Encoding Default

PowerShell のタブ文字は `t(バッククォート + t)で書きます。ダブルクォートで囲むのを忘れると展開されないので、そこだけ注意。

教訓は、カンマ区切りだと思い込まない。特に海外製ツールとか、地域設定違いの Excel が吐いた CSV はセミコロンのことがある。最初に1行メモ帳で開いて区切り文字を目で確認する。地味だけど、これが結局いちばん早い。

ちなみに -ErrorAction の効かせ方を間違えると、こういう読み込み失敗が握りつぶされて気付けないことがあります(PowerShell の ErrorAction で踏む3パターン も合わせてどうぞ)。

まとめ・チートシート

5つを1枚にまとめると、結局こんな感じ。

  • 読み書きは -Encoding必ず明示(省略は別環境で化ける)
  • 連携用は BOM なしで書き出す
  • 書き出しは -NoTypeInformation をテンプレに
  • 読んだ数値・日付は計算前にキャスト
  • 区切りは思い込まず確認して -Delimiter

バージョン差でハマりやすいので、5.1 と 7 の既定の違いも置いときます。これが頭に入ってるだけで、事故がぐっと減ります。

Windows PowerShell 5.1 と PowerShell 7 の CSV 既定挙動の比較。エンコード既定・UTF8のBOM・#TYPE行・Shift_JIS読み込み・推奨スタンスを並べた表

PowerShell の周辺は「知ってれば1分、知らないと一晩」の地雷が多い。業務スクリプト系の解説書を1冊手元に置いておくと、こういうのを調べる時間がまるっと浮きます。

このチートシート、ブックマークして使ってください。

よくある質問

Q1. Import-Csv で読んだ日本語が ? になります。直し方は?

-Encoding の指定ミスです。元ファイルが Shift_JIS なら -Encoding Default(Windows PowerShell 5.1・日本語環境)、UTF-8 なら -Encoding UTF8 を付けてください。PowerShell 7 で Shift_JIS を読むなら -Encoding Shift-JIS を明示します。

Q2. Export-Csv した CSV を Excel で開くと文字化けします。

UTF-8 BOM の有無が原因のことが多いです。Excel は BOM なし UTF-8 を Shift_JIS と誤認しがちです。Excel 連携が前提なら、-Encoding Default(ANSI 相当)で書き出すか、BOM 付き UTF-8 にするかを、相手に合わせて選んでください。

Q3. 数字の先頭の 0 が消えます(0001 → 1)。

これは PowerShell ではなく Excel 側の自動変換です。CSV 自体は文字列として 0001 を保持しているので、Excel で「データ」→「テキストとして取り込む」か、列の書式を文字列にして開けば消えません。

次に読むべき記事

以上!

同じ文字化けで時間を溶かした人いたら、どんどんシェア待ってるぜ!!


執筆者

バイブス父さん — 業務 SE 7 年 (SIer 正社員 2 / フリーランス 5)。 現職は SEO 直轄部の AI アドバイザー兼 PL、 副業で中小 SIer の CTO。 SIer の正社員からフリーランスに転じ、 複数のエージェント経由で案件を回してきた経験ベースで「業務 SE 視点」 の技術 + キャリア記事を書いています。

🐦 X: @hiro_progra0524 (日々の現場メモ更新中)
📝 About Me で経歴詳細を見る

この記事のコードと手順は ぜんぶ動作検証済み。 安心して現場で試してくれ。
バイブス父さん

現役の業務SE。C# / SQL Server 保守の現場から、コードも人もキャリアも全部書く。 実体験ベース。

運営者について