Quantcast
Channel: C#タグが付けられた新着記事 - Qiita
Viewing all articles
Browse latest Browse all 9703

.NET で PDF ファイルの日時を変更する

$
0
0
はじめに 僕は以前 Delphi でファイルの日時を変更する Windows アプリを作りました。 簡単エクスプローラ拡張 EzExpEx これは残念なことにユニコードの名称のファイルを扱えないんですよね。 最新の Delphi でビルドし直せばいいのですが、僕が持っている Delphi ではだめなんです。 これを VB.NET で作り直したいとずっと思っていました。 僕のアプリが扱えるファイルの日時は ・ファイル自体の作成日時、更新日時 ・Exif 情報の撮影日時、更新日時 ・PDF ファイルの作成日時、更新日時 ・概要情報の作成日時、更新日時 ファイル自体の日時を変更するのは .NET の標準機能で対応できますが、PDF ファイルの日時などはどうでしょう。 PDF ファイルの日時を変更する PDF ファイルは、Windows が管理するファイルそのものの日時と別に、ファイルの内容に作成日時、更新日時を持っています。 PDF ファイルが持っている日時は、.NET の標準機能で変更できません。 PDF ファイルを扱うライブラリが多く作られています。例えば ・PDFsharp - A .NET library for processing PDF ・iTextSharp ・iText for .NET これは楽でいいのですが、この方法で PDF ファイルを変更すると、読込時点でデコードされ保存時点でエンコードし直されるようです。 僕が Delphi で作ったアプリは、メタデータだけ読取して変更するようにしていました。 これを VB.NET で書き直しました。C# のコードも用意しました。 PDF ファイルの日時を取得する VB.NET Dim Path As String = "●●●●.jpg" '対象とするファイルのパス Dim CreationTime As DateTime '作成日時を返す Dim CreationValid As Boolenan = False '作成日時を取得できたか返す Dim ModTime As DateTime '更新日時を返す Dim ModValid As Boolean = False '更新日時を取得できたか返す If Not System.IO.File.Exists(Path) Then Exit Function End If Try 'ファイルを読取 Using fs As New System.IO.FileStream(Path, System.IO.FileMode.Open, System.IO.FileAccess.Read) 'PDF ファイルか確認 Dim PdfHeaderBuff As Byte() = {0, 0, 0, 0, 0} If fs.Read(PdfHeaderBuff, 0, PdfHeaderBuff.Length) <> PdfHeaderBuff.Length Then Exit Function If System.Text.Encoding.ASCII.GetString(PdfHeaderBuff).ToUpper() <> "%PDF-" Then Exit Function End If End Using Dim buff As Byte() = System.IO.File.ReadAllBytes(Path) With Me '作成日時を取得 Dim p As Long = 0 Do While p <= buff.Length - 13 If System.Text.Encoding.ASCII.GetString({buff(p), buff(p + 1), buff(p + 2), buff(p + 3), buff(p + 4), buff(p + 5), buff(p + 6), buff(p + 7), buff(p + 8), buff(p + 9), buff(p + 10), buff(p + 11), buff(p + 12)}) = "/CreationDate" Then Exit Do p += 1 Loop Do While p <= buff.Length - 3 If System.Text.Encoding.ASCII.GetString({buff(p), buff(p + 1), buff(p + 2)}) = "(D:" Then Exit Do p += 1 Loop p += 3 If p <= buff.Length - 14 Then Dim yy As Integer = CInt(System.Text.Encoding.ASCII.GetString({buff(p + 0), buff(p + 1), buff(p + 2), buff(p + 3)})) Dim mm As Integer = CInt(System.Text.Encoding.ASCII.GetString({buff(p + 4), buff(p + 5)})) Dim dd As Integer = CInt(System.Text.Encoding.ASCII.GetString({buff(p + 6), buff(p + 7)})) Dim hh As Integer = CInt(System.Text.Encoding.ASCII.GetString({buff(p + 8), buff(p + 9)})) Dim nn As Integer = CInt(System.Text.Encoding.ASCII.GetString({buff(p + 10), buff(p + 11)})) Dim ss As Integer = CInt(System.Text.Encoding.ASCII.GetString({buff(p + 12), buff(p + 13)})) CreationTime = New DateTime(yy, mm, dd, hh, nn, ss) CreationValid = True End If '更新日時を取得 p = 0 Do While p <= buff.Length - 8 If System.Text.Encoding.ASCII.GetString({buff(p), buff(p + 1), buff(p + 2), buff(p + 3), buff(p + 4), buff(p + 5), buff(p + 6), buff(p + 7)}) = "/ModDate" Then Exit Do p += 1 Loop Do While p <= buff.Length - 3 If System.Text.Encoding.ASCII.GetString({buff(p), buff(p + 1), buff(p + 2)}) = "(D:" Then Exit Do p += 1 Loop p += 3 If p <= buff.Length - 14 Then Dim yy As Integer = CInt(System.Text.Encoding.ASCII.GetString({buff(p + 0), buff(p + 1), buff(p + 2), buff(p + 3)})) Dim mm As Integer = CInt(System.Text.Encoding.ASCII.GetString({buff(p + 4), buff(p + 5)})) Dim dd As Integer = CInt(System.Text.Encoding.ASCII.GetString({buff(p + 6), buff(p + 7)})) Dim hh As Integer = CInt(System.Text.Encoding.ASCII.GetString({buff(p + 8), buff(p + 9)})) Dim nn As Integer = CInt(System.Text.Encoding.ASCII.GetString({buff(p + 10), buff(p + 11)})) Dim ss As Integer = CInt(System.Text.Encoding.ASCII.GetString({buff(p + 12), buff(p + 13)})) ModTime = New DateTime(yy, mm, dd, hh, nn, ss) ModValid = True End If End With Catch ex As Exception Exit Function End Try C# string Path = "●●●●.jpg"; // 対象とするファイルのパス DateTime CreationTime; // 作成日時を返す bool CreationValid = false; // 作成日時を取得できたか返す DateTime ModTime; // 更新日時を返す bool ModValid = false; // 更新日時を取得できたか返す if (!System.IO.File.Exists(Path)) { return false; } try { // ファイルを読取 using (System.IO.FileStream fs = new System.IO.FileStream(Path, System.IO.FileMode.Open, System.IO.FileAccess.Read)) { // PDF ファイルか確認 byte[] PdfHeaderBuff = new byte[5]; if (fs.Read(PdfHeaderBuff, 0, PdfHeaderBuff.Length) != PdfHeaderBuff.Length) return false; if (System.Text.Encoding.ASCII.GetString(PdfHeaderBuff).ToUpper() != "%PDF-") { return false; } } byte[] buff = System.IO.File.ReadAllBytes(Path); { // 作成日時を取得 long p = 0; while(p <= buff.Length - 13) { if (System.Text.Encoding.ASCII.GetString(new byte[] {buff[p], buff[p + 1], buff[p + 2], buff[p + 3], buff[p + 4], buff[p + 5], buff[p + 6], buff[p + 7], buff[p + 8], buff[p + 9], buff[p + 10], buff[p + 11], buff[p + 12]}) == "/CreationDate") break; p++; } while (p <= buff.Length - 3) { if (System.Text.Encoding.ASCII.GetString(new byte[] {buff[p], buff[p + 1], buff[p + 2]}) == "(D:") break; p++; } p += 3; if (p <= buff.Length - 14) { int yy = int.Parse(System.Text.Encoding.ASCII.GetString(new byte[] {buff[p + 0], buff[p + 1], buff[p + 2], buff[p + 3]})); int mm = int.Parse(System.Text.Encoding.ASCII.GetString(new byte[] {buff[p + 4], buff[p + 5]})); int dd = int.Parse(System.Text.Encoding.ASCII.GetString(new byte[] {buff[p + 6], buff[p + 7]})); int hh = int.Parse(System.Text.Encoding.ASCII.GetString(new byte[] {buff[p + 8], buff[p + 9]})); int nn = int.Parse(System.Text.Encoding.ASCII.GetString(new byte[] {buff[p + 10], buff[p + 11]})); int ss = int.Parse(System.Text.Encoding.ASCII.GetString(new byte[] {buff[p + 12], buff[p + 13]})); CreationTime = new DateTime(yy, mm, dd, hh, nn, ss); CreationValid = true; } // 更新日時を取得 p = 0; while (p <= buff.Length - 13) { if (System.Text.Encoding.ASCII.GetString(new byte[] {buff[p], buff[p + 1], buff[p + 2], buff[p + 3], buff[p + 4], buff[p + 5], buff[p + 6], buff[p + 7]}) == "/ModDate") break; p++; } while (p <= buff.Length - 3) { if (System.Text.Encoding.ASCII.GetString(new byte[] { buff[p], buff[p + 1], buff[p + 2] }) == "(D:") break; p++; } p += 3; if (p <= buff.Length - 14) { int yy = int.Parse(System.Text.Encoding.ASCII.GetString(new byte[] {buff[p + 0], buff[p + 1], buff[p + 2], buff[p + 3]})); int mm = int.Parse(System.Text.Encoding.ASCII.GetString(new byte[] {buff[p + 4], buff[p + 5]})); int dd = int.Parse(System.Text.Encoding.ASCII.GetString(new byte[] {buff[p + 6], buff[p + 7]})); int hh = int.Parse(System.Text.Encoding.ASCII.GetString(new byte[] {buff[p + 8], buff[p + 9]})); int nn = int.Parse(System.Text.Encoding.ASCII.GetString(new byte[] {buff[p + 10], buff[p + 11]})); int ss = int.Parse(System.Text.Encoding.ASCII.GetString(new byte[] {buff[p + 12], buff[p + 13]})); ModTime = new DateTime(yy, mm, dd, hh, nn, ss); ModValid = true; } } } catch (Exception) { return false; } PDF ファイルの日時を変更する VB.NET Dim Path As String = "●●●●.jpg" '対象とするファイルのパス Dim CreationTime As DateTime '作成日時を指定する Dim CreationValid As Boolean = True '作成日時を変更するか指定する Dim ModTime As DateTime '更新日時を指定する Dim ModValid As Boolean = True '更新日時を変更するか指定する If Not System.IO.File.Exists(Path) Then Exit Function End If Try 'ファイルを読取 Using fs As New System.IO.FileStream(Path, System.IO.FileMode.Open, System.IO.FileAccess.Read) 'PDF ファイルか確認 Dim PdfHeaderBuff As Byte() = {0, 0, 0, 0, 0} If fs.Read(PdfHeaderBuff, 0, PdfHeaderBuff.Length) <> PdfHeaderBuff.Length Then Exit Function If System.Text.Encoding.ASCII.GetString(PdfHeaderBuff).ToUpper().TrimEnd(vbNullChar) <> "%PDF-" Then Exit Function End If End Using Dim buff As Byte() = System.IO.File.ReadAllBytes(Path) With Me '作成日時を更新 If CreationValid Then Dim p As Long = 0 Do While p <= buff.Length - 13 If System.Text.Encoding.ASCII.GetString({buff(p), buff(p + 1), buff(p + 2), buff(p + 3), buff(p + 4), buff(p + 5), buff(p + 6), buff(p + 7), buff(p + 8), buff(p + 9), buff(p + 10), buff(p + 11), buff(p + 12)}) = "/CreationDate" Then Exit Do p += 1 Loop Do While p <= buff.Length - 3 If System.Text.Encoding.ASCII.GetString({buff(p), buff(p + 1), buff(p + 2)}) = "(D:" Then Exit Do p += 1 Loop p += 3 If p <= buff.Length - 14 Then Dim s As Byte() = System.Text.Encoding.ASCII.GetBytes(Format(CreationTime, "yyyyMMddHHmmss")) Buffer.BlockCopy(s, 0, buff, p, s.Length) End If '作成日時を更新 p = 0 Do While p <= buff.Length - 16 If System.Text.Encoding.ASCII.GetString({buff(p), buff(p + 1), buff(p + 2), buff(p + 3), buff(p + 4), buff(p + 5), buff(p + 6), buff(p + 7), buff(p + 8), buff(p + 9), buff(p + 10), buff(p + 11), buff(p + 12), buff(p + 13), buff(p + 14), buff(p + 15)}) = "<xmp:CreateDate>" Then Exit Do p += 1 Loop p += 16 If p <= buff.Length - 19 Then Dim s As Byte() = System.Text.Encoding.ASCII.GetBytes(Format(CreationTime, "yyyy-MM-ddTHH:mm:ss")) Buffer.BlockCopy(s, 0, buff, p, s.Length) End If End If '更新日時を更新 If CreationValid Then Dim p As Long = 0 Do While p <= buff.Length - 8 If System.Text.Encoding.ASCII.GetString({buff(p), buff(p + 1), buff(p + 2), buff(p + 3), buff(p + 4), buff(p + 5), buff(p + 6), buff(p + 7)}) = "/ModDate" Then Exit Do p += 1 Loop Do While p <= buff.Length - 3 If System.Text.Encoding.ASCII.GetString({buff(p), buff(p + 1), buff(p + 2)}) = "(D:" Then Exit Do p += 1 Loop p += 3 If p <= buff.Length - 14 Then Dim s As Byte() = System.Text.Encoding.ASCII.GetBytes(Format(ModTime, "yyyyMMddHHmmss")) Buffer.BlockCopy(s, 0, buff, p, s.Length) End If '更新日時を更新 p = 0 Do While p <= buff.Length - 16 If System.Text.Encoding.ASCII.GetString({buff(p), buff(p + 1), buff(p + 2), buff(p + 3), buff(p + 4), buff(p + 5), buff(p + 6), buff(p + 7), buff(p + 8), buff(p + 9), buff(p + 10), buff(p + 11), buff(p + 12), buff(p + 13), buff(p + 14), buff(p + 15)}) = "<xmp:ModifyDate>" Then Exit Do p += 1 Loop p += 16 If p <= buff.Length - 19 Then Dim s As Byte() = System.Text.Encoding.ASCII.GetBytes(Format(ModTime, "yyyy-MM-ddTHH:mm:ss")) Buffer.BlockCopy(s, 0, buff, p, s.Length) End If End If End With 'ファイルに書込 System.IO.File.WriteAllBytes(Path, buff) Catch ex As Exception Exit Function End Try C# string Path = "●●●●.jpg"; // 対象とするファイルのパス DateTime CreationTime; // 作成日時を指定する bool CreationValid; // 作成日時を変更するか指定する DateTime ModTime; // 更新日時を指定する bool ModValid = True; // 更新日時を変更するか指定する if (!System.IO.File.Exists(Path)) { return false; } try { // ファイルを読取 using (System.IO.FileStream fs = new System.IO.FileStream(Path, System.IO.FileMode.Open, System.IO.FileAccess.ReadWrite)) { // PDF ファイルか確認 byte[] PdfHeaderBuff = new byte[5]; if (fs.Read(PdfHeaderBuff, 0, PdfHeaderBuff.Length) != PdfHeaderBuff.Length) return false; if (System.Text.Encoding.ASCII.GetString(PdfHeaderBuff).ToUpper() != "%PDF-") { return false; } } byte[] buff = System.IO.File.ReadAllBytes(Path); { // 作成日時を更新 if (CreationValid) { int p = 0; while (p <= buff.Length - 13) { if (System.Text.Encoding.ASCII.GetString(new byte[] {buff[p], buff[p + 1], buff[p + 2], buff[p + 3], buff[p + 4], buff[p + 5], buff[p + 6], buff[p + 7], buff[p + 8], buff[p + 9], buff[p + 10], buff[p + 11], buff[p + 12]}) == "/CreationDate") break; p++; } while (p <= buff.Length - 3) { if (System.Text.Encoding.ASCII.GetString(new byte[] {buff[p], buff[p + 1], buff[p + 2]}) == "(D:") break; p++; } p += 3; if (p <= buff.Length - 14) { byte[] s = System.Text.Encoding.ASCII.GetBytes(CreationTime.ToString("yyyyMMddHHmmss")); Buffer.BlockCopy(s, 0, buff, p, s.Length); } // 作成日時を更新 p = 0; while (p <= buff.Length - 16) { if (System.Text.Encoding.ASCII.GetString(new byte[] {buff[p], buff[p + 1], buff[p + 2], buff[p + 3], buff[p + 4], buff[p + 5], buff[p + 6], buff[p + 7], buff[p + 8], buff[p + 9], buff[p + 10], buff[p + 11], buff[p + 12], buff[p + 13], buff[p + 14], buff[p + 15]}) == "<xmp:CreateDate>") break; p++; } p += 16; if (p <= buff.Length - 19) { byte[] s = System.Text.Encoding.ASCII.GetBytes(CreationTime.ToString("yyyy-MM-ddTHH:mm:ss")); Buffer.BlockCopy(s, 0, buff, p, s.Length); } } // 更新日時を更新 if (CreationValid) { int p = 0; while (p <= buff.Length - 8) { if (System.Text.Encoding.ASCII.GetString(new byte[] {buff[p], buff[p + 1], buff[p + 2], buff[p + 3], buff[p + 4], buff[p + 5], buff[p + 6], buff[p + 7]}) == "/ModDate") break; p++; } while (p <= buff.Length - 3) { if (System.Text.Encoding.ASCII.GetString(new byte[] {buff[p], buff[p + 1], buff[p + 2]}) == "(D:") break; p++; } p += 3; if (p <= buff.Length - 14) { byte[] s = System.Text.Encoding.ASCII.GetBytes(CreationTime.ToString("yyyyMMddHHmmss")); Buffer.BlockCopy(s, 0, buff, p, s.Length); } // 更新日時を更新 p = 0; while (p <= buff.Length - 16) { if (System.Text.Encoding.ASCII.GetString(new byte[] {buff[p], buff[p + 1], buff[p + 2], buff[p + 3], buff[p + 4], buff[p + 5], buff[p + 6], buff[p + 7], buff[p + 8], buff[p + 9], buff[p + 10], buff[p + 11], buff[p + 12], buff[p + 13], buff[p + 14], buff[p + 15] }) == "<xmp:ModifyDate>") break; p++; } p += 16; if (p <= buff.Length - 19) { byte[] s = System.Text.Encoding.ASCII.GetBytes(CreationTime.ToString("yyyy-MM-ddTHH:mm:ss")); Buffer.BlockCopy(s, 0, buff, p, s.Length); } } } // ファイルに書込 System.IO.File.WriteAllBytes(Path, buff); } catch (Exception) { return false; }

Viewing all articles
Browse latest Browse all 9703

Trending Articles