鏡の中
1円起業した人付き合いの苦手な普通のプログラマの日々
2026年9月5日土曜日
権力集中をしない政治体制
2026年8月11日火曜日
Macで作ったZIPの文字化け
MacでZIPを作ってWindowsに持っていき、Windowsで解凍すると文字化けする。
MacのZIPはちょっと古いもので、ヘッダにUTF-8フラグやUTF-8ファイル名を記録してくれず、そのままUTF-8ファイル名のみを保持するため、Windowsで解凍するときにそのまま文字化けしてSJISになってしまうのが原因だ。
Mac定番のKekaを使うときちんとヘッダにUTF-8ファイル名も書き込んでくれるようで、Windowsで解凍しても文字化けが起きない。
ちなみにKekaはAppStoreから落とすとサブスク?料金がかかるんだけど、本家サイトからダウンロードするとそのまま使える。
Macでも新しいZIPをbrew install zipしてやって、
/opt/homebrew/bin/zip -UN=UTF8 -r "${BASE_NAME}.zip" "$TARGET" -x "*.DS_Store" -x "__MACOSX" -x "._*"
とかやってやれば文字化けせず、.DS_Storeや._ファイル名も含めずZIPできるんだけど
そこまでやる人普通はいないので素直にKeka使ったほうがいいかもしれない。
というか、Appleちゃんとしろよ
世界中が困ってんだよ
2026年7月10日金曜日
2026年7月9日木曜日
全有権者比率での投票率
政党 | 2026 | 2024 | 2021 | 2017 |
|---|---|---|---|---|
| 自民党 | 20.66% | 約17.8% | 約19.7% | 約17.9% |
| 立憲+公明(→中道改革連合) | 約10.25% | 約18.3% | 約18.4% | 約16.7% |
| 国民民主 | 5.47% | 約6.8% | 約2.6% | 約1.4% |
| 維新 | 4.85% | 約8.7% | 約8.0% | 約3.4% |
| 共産 | 2.48% | 約3.5% | 約4.1% | 約4.0% |
| れいわ | 1.64% | 約2.9% | 約2.2% | ― |
2026年6月27日土曜日
dot_cleanしてくれる常駐アプリを作りました
最近MacbookNeoをつかいまくってて、
SDカードとか書き込んでて気がついた
そうだった。.ds_storeとか_ファイル名とか、Macを使ってると隠しファイルができてしまうのだ。
しかし!
それらを消すコマンドがある!
ターミナルを開いて、以下のコマンドを入れる
dot_clean -m /Volumes/NO\ NAME
マウントされている名前はNO NAMEなんだけど、スペースが入ってるからバックスラッシュ・スペースでつながっている
これを毎回やるのは嫌なので、
取り出しをするときにフックして、dot_cleanを実行するアプリを作ってみた。
名前はdcleanにした
xcodeを立ち上げて、アカウント入れたりなんだりしてから、contentViewやItemを消して、dcleanAppだけ残して以下のように書き換え
import SwiftUI
import AppKit
import Combine // 🌟 これを追加!
// MARK: - 1. ログのデータ構造と管理クラス
// 重複したログでも区別できるように Identifiable にする
struct LogItem: Identifiable {
let id = UUID()
let text: String
}
// ログを管理し、UI(メニューバー)を更新する専用のクラス
class LogStore: ObservableObject {
static let shared = LogStore()
@Published var logs: [LogItem] = []
// UIの更新は必ずメインスレッドで行う
func addLog(_ message: String) {
DispatchQueue.main.async {
let formatter = DateFormatter()
formatter.dateFormat = "HH:mm:ss" // 実行時間も表示
let timeString = formatter.string(from: Date())
let newLog = LogItem(text: "[\(timeString)] \(message)")
// 最新のログが一番上に来るように追加
self.logs.insert(newLog, at: 0)
// メニューが長くなりすぎないよう最新10件に制限
if self.logs.count > 10 {
self.logs.removeLast()
}
}
}
func clear() {
DispatchQueue.main.async {
self.logs.removeAll()
}
}
}
// MARK: - 2. メインのApp定義
@main
struct dcleanApp: App {
// LogStoreの変更を監視する
@StateObject private var logStore = LogStore.shared
init() {
// アプリ起動時にディスク監視を開始
DiskObserver.shared.start()
}
var body: some Scene {
MenuBarExtra("dclean", systemImage: "wand.and.stars") {
Text("外付けドライブの取り外しを監視中...")
.font(.caption)
.disabled(true)
// ログが存在する場合のみ履歴メニューを表示
if !logStore.logs.isEmpty {
Divider()
Text("最近の動作履歴")
.font(.caption)
.disabled(true)
ForEach(logStore.logs) { log in
Text(log.text)
.font(.system(size: 11)) // ログは少し小さめの文字で表示
}
Divider()
Button("履歴をクリア") {
logStore.clear()
}
}
Divider()
Button("アプリを終了") {
NSApplication.shared.terminate(nil)
}
}
.menuBarExtraStyle(.menu)
}
}
// MARK: - 3. ディスク監視クラス
class DiskObserver: NSObject {
static let shared = DiskObserver()
private override init() {
super.init()
}
func start() {
NSWorkspace.shared.notificationCenter.addObserver(
self,
selector: #selector(handleVolumeWillUnmount(_:)),
name: NSWorkspace.willUnmountNotification,
object: nil
)
}
@objc func handleVolumeWillUnmount(_ notification: Notification) {
guard let volumeURL = notification.userInfo?[NSWorkspace.volumeURLUserInfoKey] as? URL else { return }
let path = volumeURL.path
guard path.hasPrefix("/Volumes/") else { return }
// "/Volumes/USB_Drive" から "USB_Drive" の部分だけを抽出して見やすくする
let driveName = volumeURL.lastPathComponent
print("取り外しを検知: \(path) - dot_cleanを開始します。")
LogStore.shared.addLog("⏳ \(driveName) をクリーン中...")
runDotClean(for: path, driveName: driveName)
}
func runDotClean(for path: String, driveName: String) {
let task = Process()
task.launchPath = "/usr/sbin/dot_clean"
task.arguments = ["-m", path]
do {
try task.run()
task.waitUntilExit()
print("dot_clean完了: \(path) - 安全に取り外します。")
LogStore.shared.addLog("✅ \(driveName) のクリーン完了")
} catch {
print("dot_clean実行エラー: \(error.localizedDescription)")
LogStore.shared.addLog("❌ \(driveName) でエラー発生。\(error.localizedDescription)")
}
}
}
三角を押して動作確認したら、ビルド対象をAny Mac(arm64, x86_64)にして、メニューのプロダクトからアーカイブを選んでディストリビュートし、CopyAppを選んで適当なところに配置、XCODEでを終わらせて、できたAppをダブルクリックしたら動くはず
これで、いちいち、dot_cleanする必要はなくなった。
欲しい方はこちらからどうぞ
2026年06月30日バージョンから、上記説明の他にあれこれ追加して、右クリックメニューのクイックアクションにフォルダをクリーンアップするCleanupと、.DS_Storeや._ファイル名を除外しながらZIPを作るmakeCleanZipを登録する事ができるように修正しました。
2026年07月04日ネットワークドライブなども対象になっていたので、それらを除外する処理を追加しました。
2026年07月07日アプリ用アイコン作成、上部常駐部アイコン作成、下部のバーにアイコンが出てしまったのを修正
起動すると上部にアプリが常駐します。
クイックアクション設定から「Finder右クリックに追加する」で、クイックアクションが登録されます。
「Finder右クリックから削除する」でクイックアクションは消せます。
終了させるときは「アプリを終了」です。実はこれを作る前にはKekaというアプリを使っていたのですが、
ZIPしか使わないし、拙作アプリだけで良くなりました。
2026年6月21日日曜日
自動開閉ゴミ箱の回路を差し替えた
以前買ったそこそこ高い自動開閉ゴミ箱
なぜ最近、閉まらなくなってしまって
開く時と閉まる時でトルクが全然違う
ドライバーがいかれたのだろうか?
直すのも面倒なので回路ごと差し替えることにしました。
使ったのはPIC16F1825とDRV8835、GP2Y0E03、他に部品は、LEDとプルアップ抵抗4.7k2本、あとはユニバーサル基盤
開発環境はMacbookNeoで、MPLab X IDE 6.3 と snap、あとは、リボンケーブルやデュポンコネクタ、ジュンフロン線、半田、コテくらいですかね
2026年6月11日木曜日
-
どうも書かなくてはならないネタが出来てしまった。 マルチスレッドには欠かせないSleep(0)についてだ。 自分はSleep(0)を多用していた。 MSDNの記述 によると 「中断時間として 0ms を指定してこの関数を呼び出すと、現在のスレッドは自らに割り当てられている...
-
https://social.msdn.microsoft.com/Forums/vstudio/en-US/f0502813-9c4f-4b45-bab8-91f98971e407/popup-popupstaysopen-togglebutton-and-data-bindi...



